<!DOCTYPE html>
<html lang="zh-CN">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>机械臂控制系统</title>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.4.0/css/all.min.css ">
    <script src="https://cdn.socket.io/4.5.0/socket.io.min.js"></script>
    <style>
        :root {
            --bg-primary: #0f172a;
            --bg-secondary: #1e293b;
            --bg-card: #334155;
            --bg-glass: rgba(30, 41, 59, 0.9);
            --accent-blue: #3b82f6;
            --accent-green: #10b981;
            --accent-orange: #f59e0b;
            --accent-red: #ef4444;
            --accent-purple: #8b5cf6;
            --text-primary: #f1f5f9;
            --text-secondary: #cbd5e1;
            --text-muted: #64748b;
            --border-color: #475569;
            --success: #10b981;
            --warning: #f59e0b;
            --error: #ef4444;
            --glow-blue: 0 0 20px rgba(59, 130, 246, 0.4);
            --glow-green: 0 0 20px rgba(16, 185, 129, 0.4);
            --glow-red: 0 0 20px rgba(239, 68, 68, 0.4);
            --transition-base: all 0.3s ease;
        }

        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            font-family: 'Inter', 'Segoe UI', system-ui, sans-serif;
        }

        body {
            background: linear-gradient(135deg, var(--bg-primary) 0%, #1e293b 100%);
            color: var(--text-primary);
            min-height: 100vh;
            overflow-x: hidden;
            padding: 15px 0 40px;
            /* 增加底部空间 */
        }

        .container {
            max-width: 1800px;
            margin: 0 auto;
            padding: 0 20px;
            display: grid;
            grid-template-columns: 380px 1fr;
            gap: 20px;
            height: calc(100vh - 90px);
            /* 减少高度，增加底部空间 */
        }

        /* 头部样式 */
        header {
            grid-column: 1 / -1;
            display: flex;
            justify-content: space-between;
            align-items: center;
            padding: 15px 20px;
            background: var(--bg-glass);
            border-radius: 16px;
            border: 1px solid var(--border-color);
            backdrop-filter: blur(10px);
            margin-bottom: 20px;
        }

                .logo {
                    display: flex;
                    align-items: center;
                    gap: 15px;
                }

                .real-image {
            max-width: 100%;
            max-height: 100%;
            object-fit: contain;
            border-radius: 8px;
            background: rgba(30, 41, 59, 0.5);
        }

        .image-container {
            position: relative;
            width: 100%;
            height: 100%;
            display: flex;
            align-items: center;
            justify-content: center;
        }

        .image-status {
            position: absolute;
            bottom: 10px;
            left: 10px;
            background: rgba(0, 0, 0, 0.7);
            color: white;
            padding: 5px 10px;
            border-radius: 4px;
            font-size: 12px;
            z-index: 2;
        }

        /* 图像加载动画 */
        .image-loading {
            display: flex;
            align-items: center;
            justify-content: center;
            color: var(--text-muted);
        }

        .image-loading::after {
            content: '';
            width: 20px;
            height: 20px;
            border: 2px solid var(--accent-blue);
            border-top: 2px solid transparent;
            border-radius: 50%;
            animation: spin 1s linear infinite;
            margin-left: 10px;
        }

        @keyframes spin {
            0% { transform: rotate(0deg); }
            100% { transform: rotate(360deg); }
        }

        .logo-icon {
            width: 45px;
            height: 45px;
            background: linear-gradient(135deg, var(--accent-blue), var(--accent-purple));
            border-radius: 12px;
            display: flex;
            align-items: center;
            justify-content: center;
            box-shadow: var(--glow-blue);
        }

        .logo-text {
            font-size: 24px;
            font-weight: 700;
            background: linear-gradient(135deg, var(--accent-blue), var(--accent-purple));
            -webkit-background-clip: text;
            -webkit-text-fill-color: transparent;
        }

        .status-bar {
            display: flex;
            gap: 15px;
        }

        .status-item {
            display: flex;
            align-items: center;
            gap: 8px;
            padding: 8px 15px;
            background: rgba(30, 41, 59, 0.6);
            border-radius: 10px;
            border: 1px solid var(--border-color);
            backdrop-filter: blur(10px);
            font-size: 14px;
        }

        .status-dot {
            width: 10px;
            height: 10px;
            border-radius: 50%;
            background: var(--text-muted);
            position: relative;
        }

        .status-dot.active {
            background: var(--accent-green);
            box-shadow: 0 0 10px var(--accent-green);
        }

        .status-dot.active::after {
            content: '';
            position: absolute;
            width: 100%;
            height: 100%;
            border-radius: 50%;
            background: var(--accent-green);
            animation: pulse 2s infinite;
        }

        @keyframes pulse {
            0% {
                transform: scale(1);
                opacity: 0.8;
            }

            70% {
                transform: scale(2.5);
                opacity: 0;
            }

            100% {
                transform: translateY(0);
                opacity: 0;
            }
        }

        /* 左侧区域 - 控制面板+日志 */
        .left-panel {
            display: flex;
            flex-direction: column;
            gap: 20px;
        }

        /* 控制面板 */
        .control-card {
            background: var(--bg-glass);
            border-radius: 16px;
            padding: 20px;
            border: 1px solid var(--border-color);
            backdrop-filter: blur(10px);
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
            flex-shrink: 0;
        }

        .card-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 20px;
            padding-bottom: 12px;
            border-bottom: 1px solid var(--border-color);
        }

        .card-title {
            font-size: 18px;
            font-weight: 600;
            color: var(--accent-blue);
            display: flex;
            align-items: center;
            gap: 8px;
        }

        /* 控制按钮区域 */
        .control-panel {
            display: grid;
            grid-template-columns: repeat(2, 1fr);
            gap: 12px;
            margin-bottom: 18px;
        }

        .control-btn {
            background: linear-gradient(135deg, var(--bg-secondary), var(--bg-card));
            border: 1px solid var(--border-color);
            border-radius: 12px;
            padding: 12px 10px;
            color: var(--text-primary);
            cursor: pointer;
            transition: var(--transition-base);
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 6px;
            text-align: center;
        }

        .control-btn:hover {
            background: linear-gradient(135deg, var(--accent-blue), var(--accent-purple));
            box-shadow: var(--glow-blue);
            transform: translateY(-3px);
        }

        .control-btn i {
            font-size: 18px;
        }

        .btn-text {
            font-size: 12px;
            font-weight: 500;
        }

        /* 紧急控制区 */
        .emergency-control {
            display: grid;
            grid-template-columns: repeat(3, 1fr);
            gap: 10px;
            margin-bottom: 18px;
        }

        .emergency-btn {
            padding: 12px 8px;
            border: none;
            border-radius: 10px;
            color: white;
            font-weight: 600;
            cursor: pointer;
            transition: var(--transition-base);
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 6px;
            font-size: 13px;
        }

        .emergency-stop {
            background: linear-gradient(135deg, var(--accent-red), #dc2626);
        }

        .emergency-pause {
            background: linear-gradient(135deg, var(--accent-orange), #d97706);
        }

        .emergency-resume {
            background: linear-gradient(135deg, var(--accent-green), #059669);
        }

        .emergency-btn:hover {
            transform: translateY(-3px);
            box-shadow: 0 10px 20px rgba(0, 0, 0, 0.3);
        }

        .emergency-stop:hover {
            box-shadow: var(--glow-red);
        }

        .emergency-pause:hover {
            box-shadow: 0 0 20px rgba(245, 158, 11, 0.5);
        }

        .emergency-resume:hover {
            box-shadow: var(--glow-green);
        }

        /* ROS控制区 */
        .ros-control {
            display: flex;
            gap: 10px;
        }

        .ros-btn {
            flex: 1;
            padding: 10px 8px;
            border: 1px solid var(--border-color);
            border-radius: 8px;
            background: linear-gradient(135deg, var(--bg-secondary), var(--bg-card));
            color: var(--text-primary);
            cursor: pointer;
            transition: var(--transition-base);
            display: flex;
            align-items: center;
            justify-content: center;
            gap: 6px;
            font-weight: 500;
            font-size: 12px;
        }

        .ros-btn:hover {
            background: linear-gradient(135deg, var(--accent-blue), var(--accent-purple));
            box-shadow: var(--glow-blue);
        }

        /* 日志区域 - 悬浮展开设计 */
        .log-wrapper {
            position: relative;
            height: 100%;
        }

        .log-trigger {
            width: 100%;
            padding: 15px 20px;
            background: var(--bg-glass);
            border-radius: 16px;
            border: 1px solid var(--border-color);
            backdrop-filter: blur(10px);
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
            display: flex;
            align-items: center;
            justify-content: space-between;
            cursor: pointer;
            transition: var(--transition-base);
        }

        .log-trigger:hover {
            background: linear-gradient(135deg, var(--bg-secondary), var(--bg-card));
        }

        .log-trigger-text {
            display: flex;
            align-items: center;
            gap: 10px;
            font-size: 16px;
            font-weight: 500;
            color: var(--accent-purple);
        }

        .log-count {
            background: var(--accent-purple);
            color: white;
            padding: 3px 8px;
            border-radius: 12px;
            font-size: 12px;
            font-weight: 600;
        }

        /* 日志展开面板 */
        .log-panel {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: var(--bg-glass);
            border-radius: 16px;
            border: 1px solid var(--border-color);
            backdrop-filter: blur(10px);
            box-shadow: 0 10px 30px rgba(0, 0, 0, 0.3);
            padding: 20px;
            flex-direction: column;
            z-index: 10;
        }

        .log-wrapper:hover .log-panel {
            display: flex;
        }

        .log-panel-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
            padding-bottom: 10px;
            border-bottom: 1px solid var(--border-color);
        }

        .log-panel-title {
            font-size: 18px;
            font-weight: 600;
            color: var(--accent-purple);
            display: flex;
            align-items: center;
            gap: 8px;
        }

        .log-panel-actions {
            display: flex;
            gap: 10px;
        }

        .log-panel-btn {
            background: none;
            border: none;
            color: var(--text-secondary);
            cursor: pointer;
            font-size: 13px;
            padding: 5px 10px;
            border-radius: 6px;
            transition: var(--transition-base);
            display: flex;
            align-items: center;
            gap: 5px;
        }

        .log-panel-btn:hover {
            background: rgba(255, 255, 255, 0.1);
            color: var(--text-primary);
        }

        .log-container {
            flex: 1;
            background: rgba(30, 41, 59, 0.5);
            border-radius: 12px;
            padding: 15px;
            overflow-y: auto;
            font-family: 'Fira Code', monospace;
            font-size: 12px;
        }

        .log-entry {
            margin-bottom: 8px;
            padding: 8px 12px;
            border-radius: 8px;
            background: rgba(30, 41, 59, 0.3);
            display: flex;
            align-items: center;
            gap: 10px;
        }

        .log-entry.info {
            border-left: 3px solid var(--accent-blue);
        }

        .log-entry.success {
            border-left: 3px solid var(--accent-green);
        }

        .log-entry.warning {
            border-left: 3px solid var(--accent-orange);
        }

        .log-entry.error {
            border-left: 3px solid var(--accent-red);
        }

        .log-time {
            color: var(--text-muted);
            font-size: 11px;
            min-width: 80px;
        }

        /* 右侧区域 - 嵌套选项卡展示区 */
        .right-panel {
            background: var(--bg-glass);
            border-radius: 16px;
            border: 1px solid var(--border-color);
            backdrop-filter: blur(10px);
            box-shadow: 0 10px 25px rgba(0, 0, 0, 0.2);
            display: flex;
            flex-direction: column;
            overflow: hidden;
            height: calc(100vh - 160px);
            /* 增加底部空间 */
        }

        /* 一级选项卡 */
        .main-tabs {
            display: flex;
            border-bottom: 1px solid var(--border-color);
            background: rgba(30, 41, 59, 0.6);
        }

        .main-tab {
            padding: 15px 25px;
            border: none;
            background: none;
            color: var(--text-secondary);
            font-size: 15px;
            font-weight: 500;
            cursor: pointer;
            transition: var(--transition-base);
            border-bottom: 3px solid transparent;
        }

        .main-tab.active {
            color: var(--accent-blue);
            border-bottom-color: var(--accent-blue);
            background: rgba(59, 130, 246, 0.1);
        }

        .main-tab:hover:not(.active) {
            color: var(--text-primary);
            background: rgba(30, 41, 59, 0.8);
        }

        /* 二级选项卡 */
        .sub-tabs {
            display: flex;
            border-bottom: 1px solid var(--border-color);
            background: rgba(30, 41, 59, 0.4);
            padding-left: 20px;
        }

        .sub-tab {
            padding: 10px 20px;
            border: none;
            background: none;
            color: var(--text-secondary);
            font-size: 13px;
            font-weight: 500;
            cursor: pointer;
            transition: var(--transition-base);
        }

        .sub-tab.active {
            color: var(--accent-purple);
            background: rgba(139, 92, 246, 0.1);
        }

        .sub-tab:hover:not(.active) {
            color: var(--text-primary);
            background: rgba(30, 41, 59, 0.6);
        }

        /* 内容区域 - 固定大小 */
        .content-area {
            flex: 1;
            padding: 20px;
            overflow-y: auto;
            /* 固定内容区域大小，不随内容变化 */
            min-height: 0;
            display: flex;
            flex-direction: column;
        }

        .tab-content {
            display: none;
            height: 100%;
            flex-direction: column;
            overflow: hidden;
        }

        .tab-content.active {
            display: flex;
        }

        /* 图像区域 - 针对640x480优化 */
        .image-section {
            display: flex;
            flex-direction: column;
            gap: 20px;
            height: 100%;
            overflow-y: auto;
            padding-bottom: 10px;
        }

        /* 单张图片容器 */
        .single-image-container {
            position: relative;
            width: 640px;
            height: 480px;
            margin: 0 auto;
            overflow: hidden;
            border-radius: 12px;
            background: linear-gradient(135deg, #1e293b, #334155);
            display: flex;
            align-items: center;
            justify-content: center;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
            transition: transform 0.3s ease;
        }

        /* 图片对比容器 - 实现同步缩放 */
        .image-comparison-container {
            position: relative;
            width: 100%;
            max-width: 1320px;
            /* 两张640px图片 + 40px间距 */
            height: 480px;
            margin: 0 auto;
            overflow: hidden;
            border-radius: 12px;
            background: linear-gradient(135deg, #1e293b, #334155);
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.2);
        }

        .comparison-inner {
            position: absolute;
            width: 100%;
            height: 100%;
            display: flex;
            gap: 20px;
            padding: 10px;
            align-items: center;
            justify-content: center;
            transition: transform 0.3s ease;
        }

        .comparison-image {
            flex: 0 0 640px;
            height: 440px;
            border-radius: 8px;
            background: rgba(30, 41, 59, 0.5);
            display: flex;
            align-items: center;
            justify-content: center;
            overflow: hidden;
            position: relative;
        }

        /* 图片缩放控制 */
        .zoom-controls {
            position: absolute;
            bottom: 15px;
            right: 15px;
            display: flex;
            gap: 10px;
            background: rgba(0, 0, 0, 0.6);
            padding: 8px;
            border-radius: 8px;
            z-index: 5;
        }

        .zoom-btn {
            width: 30px;
            height: 30px;
            border-radius: 50%;
            background: rgba(59, 130, 246, 0.8);
            border: none;
            color: white;
            display: flex;
            align-items: center;
            justify-content: center;
            cursor: pointer;
            transition: var(--transition-base);
        }

        .zoom-btn:hover {
            background: var(--accent-blue);
            transform: scale(1.1);
        }

        .image-placeholder {
            text-align: center;
            color: var(--text-muted);
        }

        .image-placeholder i {
            font-size: 50px;
            margin-bottom: 15px;
            color: var(--accent-blue);
        }

        .image-title {
            position: absolute;
            top: 15px;
            left: 15px;
            background: rgba(0, 0, 0, 0.6);
            padding: 5px 10px;
            border-radius: 6px;
            font-size: 14px;
            font-weight: 500;
        }

        .detection-overlay {
            position: absolute;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            pointer-events: none;
        }

        .detection-box {
            position: absolute;
            border: 2px solid var(--accent-green);
            background: rgba(16, 185, 129, 0.1);
            border-radius: 6px;
        }

        .detection-label {
            position: absolute;
            background: var(--accent-green);
            color: white;
            padding: 3px 6px;
            border-radius: 4px;
            font-size: 12px;
            font-weight: 500;
            transform: translateY(-100%);
        }

        /* 数据展示区域 - 固定高度 */
        .data-display {
            background: rgba(30, 41, 59, 0.5);
            border-radius: 12px;
            padding: 20px;
            height: 100%;
            display: flex;
            flex-direction: column;
        }

        .data-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 15px;
        }

        .data-title {
            font-size: 16px;
            font-weight: 600;
            color: var(--accent-blue);
        }

        .data-actions {
            display: flex;
            gap: 10px;
        }

        .data-action-btn {
            background: none;
            border: 1px solid var(--border-color);
            color: var(--text-secondary);
            cursor: pointer;
            font-size: 12px;
            padding: 5px 10px;
            border-radius: 6px;
            transition: var(--transition-base);
            display: flex;
            align-items: center;
            gap: 5px;
        }

        .data-action-btn:hover {
            background: rgba(255, 255, 255, 0.1);
            color: var(--text-primary);
        }

        .data-content {
            flex: 1;
            overflow-y: auto;
        }

        .data-table {
            width: 100%;
            border-collapse: collapse;
            font-size: 13px;
        }

        .data-table th {
            text-align: left;
            padding: 10px 12px;
            background: rgba(30, 41, 59, 0.5);
            color: var(--accent-blue);
            font-weight: 600;
            border-bottom: 1px solid var(--border-color);
            position: sticky;
            top: 0;
        }

        .data-table td {
            padding: 10px 12px;
            border-bottom: 1px solid var(--border-color);
        }

        .data-table tr:last-child td {
            border-bottom: none;
        }

        .data-table tr:hover {
            background: rgba(30, 41, 59, 0.3);
        }

        .status-badge {
            padding: 3px 8px;
            border-radius: 12px;
            font-size: 11px;
            font-weight: 500;
        }

        .status-success {
            background: rgba(16, 185, 129, 0.2);
            color: var(--accent-green);
        }

        .status-warning {
            background: rgba(245, 158, 11, 0.2);
            color: var(--accent-orange);
        }

        .status-error {
            background: rgba(239, 68, 68, 0.2);
            color: var(--accent-red);
        }

        .status-info {
            background: rgba(59, 130, 246, 0.2);
            color: var(--accent-blue);
        }

        /* 事件数据区域 */
        .events-content {
            background: rgba(30, 41, 59, 0.5);
            border-radius: 12px;
            padding: 20px;
            height: 100%;
            display: flex;
            flex-direction: column;
        }

        .events-list {
            flex: 1;
            overflow-y: auto;
        }

        .event-item {
            padding: 12px 15px;
            border-radius: 10px;
            background: rgba(30, 41, 59, 0.3);
            margin-bottom: 10px;
            border-left: 4px solid var(--accent-blue);
            transition: var(--transition-base);
        }

        .event-item:hover {
            background: rgba(30, 41, 59, 0.5);
            transform: translateX(5px);
        }

        .event-item.error {
            border-left-color: var(--accent-red);
        }

        .event-item.warning {
            border-left-color: var(--accent-orange);
        }

        .event-item.success {
            border-left-color: var(--accent-green);
        }

        .event-header {
            display: flex;
            justify-content: space-between;
            align-items: center;
            margin-bottom: 8px;
        }

        .event-type {
            font-size: 12px;
            font-weight: 600;
            color: var(--accent-blue);
        }

        .event-item.error .event-type {
            color: var(--accent-red);
        }

        .event-item.warning .event-type {
            color: var(--accent-orange);
        }

        .event-item.success .event-type {
            color: var(--accent-green);
        }

        .event-time {
            font-size: 11px;
            color: var(--text-muted);
        }

        .event-data {
            font-size: 13px;
            color: var(--text-secondary);
            margin-bottom: 5px;
        }

        .event-message {
            font-size: 14px;
            color: var(--text-primary);
        }

        /* 响应式设计 */
        @media (max-width: 1400px) {
            .container {
                grid-template-columns: 1fr;
                height: auto;
            }

            .left-panel {
                height: auto;
            }

            .log-wrapper {
                height: 400px;
            }

            .right-panel {
                height: 800px;
                /* 响应式固定高度 */
            }

            /* 响应式调整图片大小 */
            .single-image-container {
                width: 100%;
                max-width: 640px;
                height: auto;
                aspect-ratio: 4/3;
                /* 保持640x480的比例 */
            }

            .image-comparison-container {
                height: auto;
                min-height: 480px;
            }

            .comparison-inner {
                flex-direction: column;
                height: auto;
                min-height: 480px;
            }

            .comparison-image {
                width: 100%;
                flex: none;
            }
        }

        @media (max-width: 768px) {
            .control-panel {
                grid-template-columns: 1fr;
            }

            .emergency-control {
                grid-template-columns: 1fr;
            }

            .ros-control {
                flex-direction: column;
            }

            .status-bar {
                flex-direction: column;
                gap: 10px;
            }

            header {
                flex-direction: column;
                gap: 15px;
            }

            .main-tabs {
                flex-wrap: wrap;
            }

            .main-tab {
                padding: 10px 15px;
                font-size: 13px;
            }

            .sub-tab {
                padding: 8px 12px;
                font-size: 12px;
            }
        }
    </style>
</head>

<body>
    <div class="container">
        <header>
            <div class="logo">
                <div class="logo-icon">
                    <i class="fas fa-robot"></i>
                </div>
                <div class="logo-text">机械臂控制系统</div>
            </div>
            <div class="status-bar">
                <div class="status-item">
                    <div class="status-dot active"></div>
                    <span>ROS连接正常</span>
                </div>
                <div class="status-item">
                    <div class="status-dot active"></div>
                    <span>机械臂就绪</span>
                </div>
                <div class="status-item">
                    <div class="status-dot active"></div>
                    <span>视觉系统在线</span>
                </div>
                <div class="status-item">
                    <div class="status-dot active"></div>
                    <span>数据接收中</span>
                </div>
            </div>
        </header>

        <!-- 左侧区域 -->
        <div class="left-panel">
            <!-- 控制面板 -->
            <div class="control-card">
                <div class="card-header">
                    <h2 class="card-title">
                        <i class="fas fa-sliders-h"></i> 机械臂控制面板
                    </h2>
                </div>
                <div class="control-panel">
                    <button class="control-btn" onclick="armProcess()">
                        <i class="fas fa-play-circle"></i>
                        <span class="btn-text">启动处理过程</span>
                    </button>
                    <button class="control-btn" onclick="armClearError()">
                        <i class="fas fa-redo-alt"></i>
                        <span class="btn-text">清除错误</span>
                    </button>
                    <button class="control-btn" onclick="armGoHome()">
                        <i class="fas fa-home"></i>
                        <span class="btn-text">回原点</span>
                    </button>
                    <button class="control-btn" onclick="showAdvancedControls()">
                        <i class="fas fa-cogs"></i>
                        <span class="btn-text">高级设置</span>
                    </button>
                </div>

                <div class="emergency-control">
                    <button class="emergency-btn emergency-stop" onclick="armEmergency(1)">
                        <i class="fas fa-stop-circle"></i>
                        紧急停止
                    </button>
                    <button class="emergency-btn emergency-pause" onclick="armEmergency(2)">
                        <i class="fas fa-pause-circle"></i>
                        暂停
                    </button>
                    <button class="emergency-btn emergency-resume" onclick="armEmergency(3)">
                        <i class="fas fa-play-circle"></i>
                        恢复
                    </button>
                </div>

                <div class="ros-control">
                    <button class="ros-btn" onclick="controlRosNode(1)">
                        <i class="fas fa-play"></i>
                        启动所有节点
                    </button>
                    <button class="ros-btn" onclick="controlRosNode(2)">
                        <i class="fas fa-sync-alt"></i>
                        重启所有节点
                    </button>
                    <button class="ros-btn" onclick="controlRosNode(3)">
                        <i class="fas fa-stop"></i>
                        停止所有节点
                    </button>
                </div>
            </div>

            <!-- 日志系统 - 悬浮展开 -->
            <div class="log-wrapper">
                <div class="log-panel">
                    <div class="log-panel-header">
                        <h2 class="log-panel-title">
                            <i class="fas fa-file-alt"></i> 系统日志
                        </h2>
                        <div class="log-panel-actions">
                            <button class="log-panel-btn" onclick="clearLogs()">
                                <i class="fas fa-trash"></i> 清除
                            </button>
                            <button class="log-panel-btn" onclick="exportLogs()">
                                <i class="fas fa-download"></i> 导出
                            </button>
                        </div>
                    </div>
                    <div class="log-container" id="log-container">
                        <!-- 日志将通过JS动态添加 -->
                    </div>
                </div>
            </div>
        </div>

        <!-- 右侧区域 - 嵌套选项卡 -->
        <div class="right-panel">
            <!-- 一级选项卡 -->
            <div class="main-tabs">
                <button class="main-tab active" onclick="switchMainTab('realtime')">实时数据</button>
                <button class="main-tab" onclick="switchMainTab('images')">图像监控</button>
                <button class="main-tab" onclick="switchMainTab('events')">事件记录</button>
                <button class="main-tab" onclick="switchMainTab('system')">系统状态</button>
            </div>

            <!-- 二级选项卡 - 实时数据 -->
            <div class="sub-tabs" id="sub-tabs-realtime">
                <button class="sub-tab active" onclick="switchSubTab('realtime', 'status')">状态数据</button>
                <button class="sub-tab" onclick="switchSubTab('realtime', 'position')">末端姿态</button> <!-- 修改这里 -->
                <button class="sub-tab" onclick="switchSubTab('realtime', 'joints')">关节数据</button>
                <button class="sub-tab" onclick="switchSubTab('realtime', 'sensors')">传感器数据</button>
            </div>

            <!-- 二级选项卡 - 图像监控 -->
            <div class="sub-tabs" id="sub-tabs-images" style="display: none;">
                <button class="sub-tab active" onclick="switchSubTab('images', 'original')">原始图像</button>
                <button class="sub-tab" onclick="switchSubTab('images', 'processed')">处理后图像</button>
                <button class="sub-tab" onclick="switchSubTab('images', 'comparison')">图像对比</button>
                <button class="sub-tab" onclick="switchSubTab('images', '3d')">3D视图</button>
            </div>

            <!-- 二级选项卡 - 事件记录 -->
            <div class="sub-tabs" id="sub-tabs-events" style="display: none;">
                <button class="sub-tab active" onclick="switchSubTab('events', 'all')">全部事件</button>
                <button class="sub-tab" onclick="switchSubTab('events', 'move')">移动事件</button>
                <button class="sub-tab" onclick="switchSubTab('events', 'detection')">检测事件</button>
                <button class="sub-tab" onclick="switchSubTab('events', 'error')">错误事件</button>
            </div>

            <!-- 二级选项卡 - 系统状态 -->
            <div class="sub-tabs" id="sub-tabs-system" style="display: none;">
                <button class="sub-tab active" onclick="switchSubTab('system', 'performance')">性能监控</button>
                <button class="sub-tab" onclick="switchSubTab('system', 'network')">网络状态</button>
                <button class="sub-tab" onclick="switchSubTab('system', 'settings')">系统设置</button>
                <button class="sub-tab" onclick="switchSubTab('system', 'diagnostics')">诊断信息</button>
            </div>

            <!-- 内容区域 -->
            <div class="content-area">
                <!-- 实时数据内容 -->
                <div class="tab-content active" id="content-realtime-status">
                    <div class="data-display">
                        <div class="data-header">
                            <div class="data-title">机械臂状态数据</div>
                            <div class="data-actions">
                                <button class="data-action-btn" onclick="refreshRealTimeData()">
                                    <i class="fas fa-sync-alt"></i> 刷新
                                </button>
                                <button class="data-action-btn" onclick="toggleAutoRefresh()">
                                    <i class="fas fa-play-circle"></i> 自动刷新
                                </button>
                            </div>
                        </div>
                        <div class="data-content">
                            <table class="data-table" id="status-data-table">
                                <thead>
                                    <tr>
                                        <th>参数</th>
                                        <th>值</th>
                                        <th>状态</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <!-- 状态数据将通过JS动态填充 -->
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>

                                <!-- 修改 content-realtime-position 的内容 -->
                <div class="tab-content" id="content-realtime-position">
                    <div class="data-display">
                        <div class="data-header">
                            <div class="data-title">位置数据</div>
                            <div class="data-actions">
                                <button class="data-action-btn" onclick="refreshPositionData()">
                                    <i class="fas fa-sync-alt"></i> 刷新
                                </button>
                                <button class="data-action-btn" onclick="exportPositionData()">
                                    <i class="fas fa-download"></i> 导出
                                </button>
                            </div>
                        </div>
                        
                        <!-- 实时姿态显示卡片 -->
                        <div class="pose-display" style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 20px;">
                            <div class="pose-card" style="background: rgba(30,41,59,0.3); padding: 15px; border-radius: 8px;">
                                <h4 style="color: var(--accent-blue); margin-bottom: 10px; display: flex; align-items: center; gap: 8px;">
                                    <i class="fas fa-arrows-alt"></i> 位置 (m)
                                </h4>
                                <div class="pose-values">
                                    <div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
                                        <span style="color: var(--text-secondary);">末端X:</span>
                                        <span id="current-pose-x" style="font-weight: 600; color: var(--accent-green);">0.000</span>
                                    </div>
                                    <div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
                                        <span style="color: var(--text-secondary);">末端Y:</span>
                                        <span id="current-pose-y" style="font-weight: 600; color: var(--accent-green);">0.000</span>
                                    </div>
                                    <div style="display: flex; justify-content: space-between;">
                                        <span style="color: var(--text-secondary);">末端Z:</span>
                                        <span id="current-pose-z" style="font-weight: 600; color: var(--accent-green);">0.000</span>
                                    </div>
                                </div>
                            </div>
                            <div class="pose-card" style="background: rgba(30,41,59,0.3); padding: 15px; border-radius: 8px;">
                                <h4 style="color: var(--accent-blue); margin-bottom: 10px; display: flex; align-items: center; gap: 8px;">
                                    <i class="fas fa-sync-alt"></i> 旋转 (度)
                                </h4>
                                <div class="pose-values">
                                    <div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
                                        <span style="color: var(--text-secondary);">Rx:</span>
                                        <span id="current-pose-rx" style="font-weight: 600; color: var(--accent-orange);">0.00</span>
                                    </div>
                                    <div style="display: flex; justify-content: space-between; margin-bottom: 8px;">
                                        <span style="color: var(--text-secondary);">Ry:</span>
                                        <span id="current-pose-ry" style="font-weight: 600; color: var(--accent-orange);">0.00</span>
                                    </div>
                                    <div style="display: flex; justify-content: space-between;">
                                        <span style="color: var(--text-secondary);">Rz:</span>
                                        <span id="current-pose-rz" style="font-weight: 600; color: var(--accent-orange);">0.00</span>
                                    </div>
                                </div>
                            </div>
                        </div>
                        
                        <div class="data-content">
                            <table class="data-table" id="position-data-table">
                                <thead>
                                    <tr>
                                        <th>时间戳</th>
                                        <th>X (m)</th>
                                        <th>Y (m)</th>
                                        <th>Z (m)</th>
                                        <th>Rx (°)</th>
                                        <th>Ry (°)</th>
                                        <th>Rz (°)</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <!-- 位置数据将通过JS动态填充 -->
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>

                <div class="tab-content" id="content-realtime-joints">
                    <div class="data-display">
                        <div class="data-header">
                            <div class="data-title">关节数据</div>
                            <div class="data-actions">
                                <button class="data-action-btn" onclick="refreshJointsData()">
                                    <i class="fas fa-sync-alt"></i> 刷新
                                </button>
                                <button class="data-action-btn" onclick="exportJointsData()">
                                    <i class="fas fa-download"></i> 导出
                                </button>
                            </div>
                        </div>
                        <div class="data-content">
                            <table class="data-table" id="joints-data-table">
                                <thead>
                                    <tr>
                                        <th>关节</th>
                                        <th>角度 (rad)</th>
                                        <th>速度 (rad/s)</th>
                                        <th>扭矩 (Nm)</th>
                                        <th>电流 (A)</th>
                                        <th>温度 (°C)</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <!-- 关节数据将通过JS动态填充 -->
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>

                <div class="tab-content" id="content-realtime-sensors">
                    <div class="data-display">
                        <div class="data-header">
                            <div class="data-title">传感器数据</div>
                            <div class="data-actions">
                                <button class="data-action-btn" onclick="refreshSensorsData()">
                                    <i class="fas fa-sync-alt"></i> 刷新
                                </button>
                                <button class="data-action-btn" onclick="exportSensorsData()">
                                    <i class="fas fa-download"></i> 导出
                                </button>
                            </div>
                        </div>
                        <div class="data-content">
                            <table class="data-table" id="sensors-data-table">
                                <thead>
                                    <tr>
                                        <th>传感器</th>
                                        <th>类型</th>
                                        <th>数值</th>
                                        <th>单位</th>
                                        <th>状态</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <!-- 传感器数据将通过JS动态填充 -->
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>

                <!-- 图像监控内容 - 针对640x480优化 -->
                <div class="tab-content" id="content-images-original">
                    <div class="image-section">
                        <div class="single-image-container" id="image-container-1">
                            <div class="image-title">原始图像</div>
                            <div class="image-placeholder">
                                <i class="fas fa-camera"></i>
                                <p>等待图像数据...</p>
                            </div>
                            <div class="detection-overlay" id="detection-overlay-1">
                                <!-- 检测框将通过JS动态添加 -->
                            </div>
                            <div class="zoom-controls">
                                <button class="zoom-btn" onclick="zoomImage('image-container-1', -0.1)">
                                    <i class="fas fa-search-minus"></i>
                                </button>
                                <button class="zoom-btn" onclick="zoomImage('image-container-1', 0.1)">
                                    <i class="fas fa-search-plus"></i>
                                </button>
                                <button class="zoom-btn" onclick="resetZoom('image-container-1')">
                                    <i class="fas fa-compress-arrows-alt"></i>
                                </button>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="tab-content" id="content-images-processed">
                    <div class="image-section">
                        <div class="single-image-container" id="image-container-2">
                            <div class="image-title">处理后的图像</div>
                            <div class="image-placeholder">
                                <i class="fas fa-camera"></i>
                                <p>等待图像数据...</p>
                            </div>
                            <div class="detection-overlay" id="detection-overlay-2">
                                <!-- 检测框将通过JS动态添加 -->
                            </div>
                            <div class="zoom-controls">
                                <button class="zoom-btn" onclick="zoomImage('image-container-2', -0.1)">
                                    <i class="fas fa-search-minus"></i>
                                </button>
                                <button class="zoom-btn" onclick="zoomImage('image-container-2', 0.1)">
                                    <i class="fas fa-search-plus"></i>
                                </button>
                                <button class="zoom-btn" onclick="resetZoom('image-container-2')">
                                    <i class="fas fa-compress-arrows-alt"></i>
                                </button>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="tab-content" id="content-images-comparison">
                    <div class="image-section">
                        <div class="image-comparison-container" id="comparison-container">
                            <div class="comparison-inner" id="comparison-inner">
                                <div class="comparison-image" id="comparison-image-1">
                                    <div class="image-title">原始图像</div>
                                    <div class="image-placeholder">
                                        <i class="fas fa-camera"></i>
                                        <p>等待图像数据...</p>
                                    </div>
                                    <div class="detection-overlay" id="comparison-detection-1">
                                        <!-- 检测框将通过JS动态添加 -->
                                    </div>
                                </div>
                                <div class="comparison-image" id="comparison-image-2">
                                    <div class="image-title">处理后的图像</div>
                                    <div class="image-placeholder">
                                        <i class="fas fa-camera"></i>
                                        <p>等待图像数据...</p>
                                    </div>
                                    <div class="detection-overlay" id="comparison-detection-2">
                                        <!-- 检测框将通过JS动态添加 -->
                                    </div>
                                </div>
                            </div>
                            <div class="zoom-controls">
                                <button class="zoom-btn" onclick="zoomComparison(-0.1)">
                                    <i class="fas fa-search-minus"></i>
                                </button>
                                <button class="zoom-btn" onclick="zoomComparison(0.1)">
                                    <i class="fas fa-search-plus"></i>
                                </button>
                                <button class="zoom-btn" onclick="resetComparisonZoom()">
                                    <i class="fas fa-compress-arrows-alt"></i>
                                </button>
                            </div>
                        </div>
                    </div>
                </div>

                <div class="tab-content" id="content-images-3d">
                    <div class="image-section">
                        <div class="single-image-container" id="image-container-3d">
                            <div class="image-title">3D视图</div>
                            <div class="image-placeholder">
                                <i class="fas fa-cube"></i>
                                <p>等待3D模型数据...</p>
                            </div>
                            <div class="zoom-controls">
                                <button class="zoom-btn" onclick="zoomImage('image-container-3d', -0.1)">
                                    <i class="fas fa-search-minus"></i>
                                </button>
                                <button class="zoom-btn" onclick="zoomImage('image-container-3d', 0.1)">
                                    <i class="fas fa-search-plus"></i>
                                </button>
                                <button class="zoom-btn" onclick="resetZoom('image-container-3d')">
                                    <i class="fas fa-compress-arrows-alt"></i>
                                </button>
                            </div>
                        </div>
                    </div>
                </div>

                <!-- 事件记录内容 -->
                <div class="tab-content" id="content-events-all">
                    <div class="events-content">
                        <div class="data-header">
                            <div class="data-title">全部事件记录</div>
                            <div class="data-actions">
                                <button class="data-action-btn" onclick="clearEvents()">
                                    <i class="fas fa-trash"></i> 清除
                                </button>
                                <button class="data-action-btn" onclick="exportEvents()">
                                    <i class="fas fa-download"></i> 导出
                                </button>
                            </div>
                        </div>
                        <div class="events-list" id="events-container-all">
                            <!-- 事件数据将通过JS动态填充 -->
                        </div>
                    </div>
                </div>

                <div class="tab-content" id="content-events-move">
                    <div class="events-content">
                        <div class="data-header">
                            <div class="data-title">移动事件记录</div>
                            <div class="data-actions">
                                <button class="data-action-btn" onclick="clearMoveEvents()">
                                    <i class="fas fa-trash"></i> 清除
                                </button>
                                <button class="data-action-btn" onclick="exportMoveEvents()">
                                    <i class="fas fa-download"></i> 导出
                                </button>
                            </div>
                        </div>
                        <div class="events-list" id="events-container-move">
                            <!-- 移动事件数据将通过JS动态填充 -->
                        </div>
                    </div>
                </div>

                <div class="tab-content" id="content-events-detection">
                    <div class="events-content">
                        <div class="data-header">
                            <div class="data-title">检测事件记录</div>
                            <div class="data-actions">
                                <button class="data-action-btn" onclick="clearDetectionEvents()">
                                    <i class="fas fa-trash"></i> 清除
                                </button>
                                <button class="data-action-btn" onclick="exportDetectionEvents()">
                                    <i class="fas fa-download"></i> 导出
                                </button>
                            </div>
                        </div>
                        <div class="events-list" id="events-container-detection">
                            <!-- 检测事件数据将通过JS动态填充 -->
                        </div>
                    </div>
                </div>

                <div class="tab-content" id="content-events-error">
                    <div class="events-content">
                        <div class="data-header">
                            <div class="data-title">错误事件记录</div>
                            <div class="data-actions">
                                <button class="data-action-btn" onclick="clearErrorEvents()">
                                    <i class="fas fa-trash"></i> 清除
                                </button>
                                <button class="data-action-btn" onclick="exportErrorEvents()">
                                    <i class="fas fa-download"></i> 导出
                                </button>
                            </div>
                        </div>
                        <div class="events-list" id="events-container-error">
                            <!-- 错误事件数据将通过JS动态填充 -->
                        </div>
                    </div>
                </div>

                <!-- 系统状态内容 -->
                <div class="tab-content" id="content-system-performance">
                    <div class="data-display">
                        <div class="data-header">
                            <div class="data-title">系统性能监控</div>
                            <div class="data-actions">
                                <button class="data-action-btn" onclick="refreshPerformanceData()">
                                    <i class="fas fa-sync-alt"></i> 刷新
                                </button>
                                <button class="data-action-btn" onclick="exportPerformanceData()">
                                    <i class="fas fa-download"></i> 导出
                                </button>
                            </div>
                        </div>
                        <div class="data-content">
                            <table class="data-table" id="performance-data-table">
                                <thead>
                                    <tr>
                                        <th>组件</th>
                                        <th>CPU使用率</th>
                                        <th>内存使用率</th>
                                        <th>温度</th>
                                        <th>状态</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <!-- 性能数据将通过JS动态填充 -->
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>

                <div class="tab-content" id="content-system-network">
                    <div class="data-display">
                        <div class="data-header">
                            <div class="data-title">网络状态</div>
                            <div class="data-actions">
                                <button class="data-action-btn" onclick="refreshNetworkData()">
                                    <i class="fas fa-sync-alt"></i> 刷新
                                </button>
                                <button class="data-action-btn" onclick="exportNetworkData()">
                                    <i class="fas fa-download"></i> 导出
                                </button>
                            </div>
                        </div>
                        <div class="data-content">
                            <table class="data-table" id="network-data-table">
                                <thead>
                                    <tr>
                                        <th>连接</th>
                                        <th>IP地址</th>
                                        <th>上传速度</th>
                                        <th>下载速度</th>
                                        <th>延迟</th>
                                    </tr>
                                </thead>
                                <tbody>
                                    <!-- 网络数据将通过JS动态填充 -->
                                </tbody>
                            </table>
                        </div>
                    </div>
                </div>
            </div>
        </div>
    </div>

    <script>
        // 存储图片缩放比例
        const imageZoomLevels = {
            'image-container-1': 1,
            'image-container-2': 1,
            'image-container-3d': 1,
            'comparison-container': 1 // 图片对比的统一缩放比例
        };

        // 修改模拟数据，在成功点数上下添加总点数和成功率
        const mockStatusData = [
            { parameter: '运行状态', value: '待机', status: '正常', statusClass: 'status-success' },
            { parameter: '总点数', value: '12', status: '完成', statusClass: 'status-success' }, // 新增总点数
            { parameter: '成功点数', value: '8/12', status: '良好', statusClass: 'status-success' },
            { parameter: '成功率', value: '66.7%', status: '良好', statusClass: 'status-success' }, // 新增成功率
            { parameter: '当前点ID', value: '3', status: '进行中', statusClass: 'status-warning' },
            { parameter: '当前点坐标', value: 'X: 0.000, Y: 0.000', status: '待命', statusClass: 'status-info' },
            { parameter: '电池电量', value: '87%', status: '良好', statusClass: 'status-success' },
            { parameter: '运行时间', value: '2小时34分', status: '正常', statusClass: 'status-info' },
            { parameter: '系统温度', value: '42°C', status: '正常', statusClass: 'status-info' },
            { parameter: '网络延迟', value: '23ms', status: '良好', statusClass: 'status-success' },
            { parameter: '负载状态', value: '0.85kg', status: '正常', statusClass: 'status-info' },
            { parameter: '控制模式', value: '自动', status: '运行中', statusClass: 'status-success' },
            { parameter: '错误代码', value: '0x0000', status: '无错误', statusClass: 'status-success' }
        ];

        const mockPositionData = [
            { timestamp: '12:34:56.789', x: 1.234567, y: 2.345678, z: 0.123456, duration: '02:34:12' },
            { timestamp: '12:34:56.690', x: 1.234512, y: 2.345612, z: 0.123412, duration: '02:34:11' },
            { timestamp: '12:34:56.591', x: 1.234457, y: 2.345546, z: 0.123368, duration: '02:34:10' },
            { timestamp: '12:34:56.492', x: 1.234402, y: 2.345480, z: 0.123324, duration: '02:34:09' },
            { timestamp: '12:34:56.393', x: 1.234347, y: 2.345414, z: 0.123280, duration: '02:34:08' },
            { timestamp: '12:34:56.294', x: 1.234292, y: 2.345348, z: 0.123236, duration: '02:34:07' },
            { timestamp: '12:34:56.195', x: 1.234237, y: 2.345282, z: 0.123192, duration: '02:34:06' }
        ];

        const mockJointsData = [
            { joint: '关节1', angle: '-1.12', speed: '0.0', torque: '0.85', current: '0.12', temperature: '32' },
            { joint: '关节2', angle: '1.79', speed: '0.0', torque: '1.23', current: '0.18', temperature: '34' },
            { joint: '关节3', angle: '-1.28', speed: '0.0', torque: '0.96', current: '0.15', temperature: '36' },
            { joint: '关节4', angle: '0.00', speed: '0.0', torque: '0.45', current: '0.08', temperature: '31' },
            { joint: '关节5', angle: '-0.51', speed: '0.0', torque: '0.67', current: '0.10', temperature: '38' },
            { joint: '关节6', angle: '4.09', speed: '0.0', torque: '0.89', current: '0.13', temperature: '33' }
        ];

        const mockSensorsData = [
            { sensor: '末端力传感器', type: '力反馈', value: '2.35', unit: 'N', status: '正常', statusClass: 'status-success' },
            { sensor: '视觉传感器', type: '图像', value: '640x480', unit: '像素', status: '正常', statusClass: 'status-success' },
            { sensor: '红外传感器', type: '距离', value: '0.56', unit: 'm', status: '正常', statusClass: 'status-success' },
            { sensor: '温度传感器', type: '温度', value: '38.2', unit: '°C', status: '注意', statusClass: 'status-warning' },
            { sensor: '湿度传感器', type: '湿度', value: '45', unit: '%', status: '正常', statusClass: 'status-success' },
            { sensor: '碰撞传感器', type: '安全', value: '0', unit: '次', status: '正常', statusClass: 'status-success' }
        ];

        const mockPerformanceData = [
            { component: '主控CPU', cpu: '45%', memory: '32%', temperature: '58°C', status: '正常', statusClass: 'status-success' },
            { component: '视觉处理单元', cpu: '68%', memory: '56%', temperature: '62°C', status: '高负载', statusClass: 'status-warning' },
            { component: '运动控制模块', cpu: '23%', memory: '18%', temperature: '45°C', status: '正常', statusClass: 'status-success' },
            { component: '通信模块', cpu: '15%', memory: '12%', temperature: '41°C', status: '正常', statusClass: 'status-success' }
        ];

        const mockNetworkData = [
            { connection: 'ROS主节点', ip: '192.168.1.101', upload: '1.2 Mbps', download: '3.5 Mbps', latency: '12 ms' },
            { connection: '视觉系统', ip: '192.168.1.102', upload: '5.8 Mbps', download: '0.3 Mbps', latency: '8 ms' },
            { connection: '控制终端', ip: '192.168.1.103', upload: '0.5 Mbps', download: '0.8 Mbps', latency: '5 ms' },
            { connection: '云服务器', ip: '203.0.113.45', upload: '0.2 Mbps', download: '0.5 Mbps', latency: '45 ms' }
        ];

        const mockEvents = {
            all: [
                {
                    type: 'move_point',
                    time: '12:34:56',
                    message: '移动到目标点 ID: 3',
                    data: '坐标: X=1.234567, Y=2.345678, Z=0.123456',
                    class: ''
                },
                {
                    type: 'detection',
                    time: '12:34:50',
                    message: '检测到5个有效点',
                    data: '总点数: 12, 有效点数: 5',
                    class: 'success'
                },
                {
                    type: 'emergency',
                    time: '12:34:45',
                    message: '急停按钮按下',
                    data: '系统暂停运行',
                    class: 'error'
                },
                {
                    type: 'move_complete',
                    time: '12:34:40',
                    message: '移动任务完成',
                    data: '成功率: 100%, 耗时: 2.4s',
                    class: 'success'
                },
                {
                    type: 'error',
                    time: '12:34:35',
                    message: '关节3温度过高',
                    data: '温度: 65°C, 超过阈值',
                    class: 'error'
                },
                {
                    type: 'status',
                    time: '12:34:30',
                    message: '系统状态更新',
                    data: '电池电量: 87%, 运行时间: 2小时34分',
                    class: 'info'
                }
            ],
            move: [
                {
                    type: 'move_point',
                    time: '12:34:56',
                    message: '移动到目标点 ID: 3',
                    data: '坐标: X=1.234567, Y=2.345678, Z=0.123456',
                    class: ''
                },
                {
                    type: 'move_complete',
                    time: '12:34:40',
                    message: '移动任务完成',
                    data: '成功率: 100%, 耗时: 2.4s',
                    class: 'success'
                }
            ],
            detection: [
                {
                    type: 'detection',
                    time: '12:34:50',
                    message: '检测到5个有效点',
                    data: '总点数: 12, 有效点数: 5',
                    class: 'success'
                }
            ],
            error: [
                {
                    type: 'emergency',
                    time: '12:34:45',
                    message: '急停按钮按下',
                    data: '系统暂停运行',
                    class: 'error'
                },
                {
                    type: 'error',
                    time: '12:34:35',
                    message: '关节3温度过高',
                    data: '温度: 65°C, 超过阈值',
                    class: 'error'
                }
            ]
        };

        // 初始化页面
        document.addEventListener('DOMContentLoaded', function () {
            // 初始更新所有数据
            console.log('🚀 页面初始化开始');
            
            // 初始更新所有数据
            updateStatusData(mockStatusData);
            updatePositionData(mockPositionData);
            updateJointsData(mockJointsData);
            updateSensorsData(mockSensorsData);
            updatePerformanceData(mockPerformanceData);
            updateNetworkData(mockNetworkData);
            updateCurrentPose(currentPose);
            updateEvents();

            addImageRefreshControls();

            // 添加初始日志
            addLog("系统初始化完成", "success");
            addLog("ROS节点连接成功", "info");
            addLog("机械臂校准完成", "success");
            addLog("视觉系统启动", "info");

            // 创建模拟检测框
            createDetectionBoxes();

            // 初始化WebSocket连接
            initWebSocket();

            // 模拟实时数据更新（作为后备）
            setInterval(() => {
                if (!useRealData) {
                    simulateDataUpdate();
                }
            }, 3000);
            
        // 添加一些测试事件到系统日志
            setTimeout(() => {
                addLog("机械臂系统启动完成", "success");
                addLog("视觉检测系统就绪", "info");
                addLog("ROS节点连接正常", "success");
            }, 1000);
            
            // 模拟一些事件来测试日志显示
            setTimeout(() => {
                addLog("移动事件: 移动到目标点 ID: 1", "info");
                addLog("检测事件: 检测到3个有用点，总共8个位置", "info");
                addLog("移动完成: 点1移动完成 - 成功", "success");
            }, 2000);
            
            setTimeout(() => {
                addLog("错误事件: 关节3温度过高 - 65°C", "error");
                addLog("移动事件: 移动到目标点 ID: 2", "info");
            }, 3000);

            startStatusMonitoring();
    
            // 添加测试状态数据的函数（调试用）
            window.testStatusData = function() {
                const testData = {
                    running_status: 'moving',
                    success_count: 9,
                    total_count: 12,
                    current_point_id: 4,
                    battery: 85,
                    temperature: 43,
                    operation_time: '2小时35分',
                    network_delay: 25,
                    load_status: 0.82,
                    control_mode: 'auto',
                    error_code: '0x0000'
                };
                
                handleStatusData({ data: testData });
                addLog('测试状态数据已应用', 'success');
            };
            const initialCoordinate = {
                world_coord: { x: 0, y: 0 },
                is_moving: false,
                is_completed: false
            };
            updateCurrentPointCoordinate(initialCoordinate);
            // 设置默认的总点数和成功点数
            updateTotalPoints(12, '完成');
            updateSuccessPoints(8, 12, '完成');
            console.log('✅ 页面初始化完成');
        });

        // 在全局变量部分添加真实数据状态跟踪
        let realDataStatus = {
            endEffector: false,
            joints: false,
            status: false,
            lastRealDataTime: null
        };

        // 切换一级选项卡
        function switchMainTab(tabName) {
            // 隐藏所有二级选项卡容器
            document.querySelectorAll('[id^="sub-tabs-"]').forEach(tab => {
                tab.style.display = 'none';
            });

            // 隐藏所有内容区域
            document.querySelectorAll('.tab-content').forEach(content => {
                content.classList.remove('active');
            });

            // 移除所有一级选项卡的活动状态
            document.querySelectorAll('.main-tab').forEach(tab => {
                tab.classList.remove('active');
            });

            // 激活当前一级选项卡
            document.querySelector(`.main-tab[onclick="switchMainTab('${tabName}')"]`).classList.add('active');

            // 显示对应的二级选项卡容器
            document.getElementById(`sub-tabs-${tabName}`).style.display = 'flex';

            // 显示对应内容区域的第一个子选项
            const firstSubTab = document.querySelector(`#sub-tabs-${tabName} .sub-tab`).getAttribute('onclick').match(/'([^']+)'/g)[1];
            switchSubTab(tabName, firstSubTab);
        }

        // 切换二级选项卡
        function switchSubTab(mainTab, subTab) {
            // 移除当前主选项卡下所有二级选项卡的活动状态
            document.querySelectorAll(`#sub-tabs-${mainTab} .sub-tab`).forEach(tab => {
                tab.classList.remove('active');
            });

            // 隐藏当前主选项卡下所有内容区域
            document.querySelectorAll('[id^="content-' + mainTab + '-"]').forEach(content => {
                content.classList.remove('active');
            });

            // 激活当前二级选项卡
            document.querySelector(`#sub-tabs-${mainTab} .sub-tab[onclick="switchSubTab('${mainTab}', '${subTab}')"]`).classList.add('active');

            // 显示对应的内容区域
            document.getElementById(`content-${mainTab}-${subTab}`).classList.add('active');
        }

        // 初始化WebSocket连接
        let socket = null;
        let useRealData = false;
        let currentPose = { x: 0, y: 0, z: 0, rx: 0, ry: 0, rz: 0 };

        // 在全局变量部分添加
        let jointsData = {}; // 存储关节数据的对象
        let jointCurrents = []; // 存储关节电流数据
        let operationStartTime = null; // 运行开始时间
        let operationTimer = null;     // 运行时间定时器
        let isUsingRealData = false;   // 是否使用真实数据
        let hasReceivedFirstEvent = false; // 是否已收到第一个事件

        // 在全局变量部分添加图像数据存储
        let imageData = {
            original: null,
            processed: null,
            lastUpdate: {
                original: null,
                processed: null
            }
        };

        // 修改现有的handleImageData函数，确保正确处理base64数据
        function handleImageData(eventType, data) {
            console.log('🖼️ 处理图像数据:', eventType, data);
            
            if (!data) {
                console.warn('图像数据为空');
                return;
            }
            
            // 检查数据格式，支持多种可能的base64字段名
            let base64Data = data.base64_data || data.data || data.image_data;
            
            if (!base64Data) {
                console.warn('未找到有效的base64图像数据:', data);
                return;
            }
            
            const imageSize = data.image_size || data.data_length || 0;
            
            console.log(`📸 接收图像数据: ${eventType}, 大小: ${imageSize} 字节, base64长度: ${base64Data.length}`);
            
            try {
                // 根据事件类型确定显示位置
                if (eventType === 'image_show') {
                    // 原始图像
                    imageData.original = base64Data;
                    imageData.lastUpdate.original = new Date();
                    displayOriginalImage(base64Data);
                    addLog(`原始图像已更新 (${(imageSize / 1024).toFixed(1)} KB)`, "success");
                } else if (eventType === 'image_detection') {
                    // 处理后的图像
                    imageData.processed = base64Data;
                    imageData.lastUpdate.processed = new Date();
                    displayProcessedImage(base64Data);
                    addLog(`处理后的图像已更新 (${(imageSize / 1024).toFixed(1)} KB)`, "success");
                }
                
                // 同时更新对比视图
                updateComparisonImages();
                
            } catch (error) {
                console.error('处理图像数据时出错:', error);
                addLog(`图像显示错误: ${error.message}`, "error");
            }
        }

        // 增强显示原始图像函数
        function displayOriginalImage(base64Data) {
            try {
                const container = document.getElementById('image-container-1');
                if (!container) {
                    console.error('原始图像容器未找到');
                    return;
                }
                
                const placeholder = container.querySelector('.image-placeholder');
                const overlay = document.getElementById('detection-overlay-1');
                
                // 隐藏占位符
                if (placeholder) {
                    placeholder.style.display = 'none';
                }
                
                // 清理可能存在的旧图像
                const oldImg = container.querySelector('.real-image');
                if (oldImg) {
                    oldImg.remove();
                }
                
                // 创建图像元素
                const img = document.createElement('img');
                img.className = 'real-image';
                img.style.width = '100%';
                img.style.height = '100%';
                img.style.objectFit = 'contain';
                img.style.borderRadius = '8px';
                img.style.background = 'rgba(30, 41, 59, 0.5)';
                
                // 添加加载状态
                img.style.opacity = '0';
                img.style.transition = 'opacity 0.3s ease';
                
                // 设置图像源
                img.src = `data:image/jpeg;base64,${base64Data}`;
                img.alt = '实时原始图像';
                
                // 图像加载完成后的处理
                img.onload = function() {
                    img.style.opacity = '1';
                    console.log('✅ 原始图像加载完成');
                    
                    // 添加图像信息显示
                    updateImageInfo(container, '原始图像', imageData.lastUpdate.original);
                };
                
                img.onerror = function() {
                    console.error('原始图像加载失败');
                    if (placeholder) {
                        placeholder.style.display = 'flex';
                        placeholder.innerHTML = `
                            <i class="fas fa-exclamation-circle"></i>
                            <p>图像加载失败</p>
                        `;
                    }
                };
                
                // 插入到容器中（在检测覆盖层之前）
                if (overlay) {
                    container.insertBefore(img, overlay);
                } else {
                    container.appendChild(img);
                }
                
            } catch (error) {
                console.error('显示原始图像时出错:', error);
            }
        }

                // 新增：更新图像信息显示
        function updateImageInfo(container, title, updateTime) {
            // 移除旧的信息显示
            const oldInfo = container.querySelector('.image-info');
            if (oldInfo) {
                oldInfo.remove();
            }
            
            const info = document.createElement('div');
            info.className = 'image-info';
            info.style.position = 'absolute';
            info.style.bottom = '10px';
            info.style.left = '10px';
            info.style.background = 'rgba(0, 0, 0, 0.7)';
            info.style.color = 'white';
            info.style.padding = '5px 10px';
            info.style.borderRadius = '4px';
            info.style.fontSize = '12px';
            info.style.zIndex = '2';
            
            const timeStr = updateTime ? updateTime.toLocaleTimeString() : '未知';
            info.innerHTML = `${title} - ${timeStr}`;
            
            container.appendChild(info);
        }

        // 增强显示处理后图像函数
        function displayProcessedImage(base64Data) {
            try {
                const container = document.getElementById('image-container-2');
                if (!container) {
                    console.error('处理后图像容器未找到');
                    return;
                }
                
                const placeholder = container.querySelector('.image-placeholder');
                const overlay = document.getElementById('detection-overlay-2');
                
                if (placeholder) {
                    placeholder.style.display = 'none';
                }
                
                // 清理旧图像
                const oldImg = container.querySelector('.real-image');
                if (oldImg) {
                    oldImg.remove();
                }
                
                // 创建图像元素
                const img = document.createElement('img');
                img.className = 'real-image';
                img.style.width = '100%';
                img.style.height = '100%';
                img.style.objectFit = 'contain';
                img.style.borderRadius = '8px';
                img.style.background = 'rgba(30, 41, 59, 0.5)';
                img.style.opacity = '0';
                img.style.transition = 'opacity 0.3s ease';
                
                img.src = `data:image/jpeg;base64,${base64Data}`;
                img.alt = '处理后图像';
                
                img.onload = function() {
                    img.style.opacity = '1';
                    console.log('✅ 处理后图像加载完成');
                    updateImageInfo(container, '处理后图像', imageData.lastUpdate.processed);
                };
                
                img.onerror = function() {
                    console.error('处理后图像加载失败');
                    if (placeholder) {
                        placeholder.style.display = 'flex';
                        placeholder.innerHTML = `
                            <i class="fas fa-exclamation-circle"></i>
                            <p>图像加载失败</p>
                        `;
                    }
                };
                
                if (overlay) {
                    container.insertBefore(img, overlay);
                } else {
                    container.appendChild(img);
                }
                
            } catch (error) {
                console.error('显示处理后图像时出错:', error);
            }
        }

        // 增强对比视图更新函数
        function updateComparisonImages() {
            try {
                const comparison1 = document.getElementById('comparison-image-1');
                const comparison2 = document.getElementById('comparison-image-2');
                
                // 更新对比视图中的原始图像
                if (imageData.original && comparison1) {
                    const placeholder1 = comparison1.querySelector('.image-placeholder');
                    const overlay1 = document.getElementById('comparison-detection-1');
                    
                    if (placeholder1) {
                        placeholder1.style.display = 'none';
                    }
                    
                    // 清理旧图像
                    const oldImg1 = comparison1.querySelector('.real-image');
                    if (oldImg1) {
                        oldImg1.remove();
                    }
                    
                    const img1 = document.createElement('img');
                    img1.className = 'real-image';
                    img1.style.width = '100%';
                    img1.style.height = '100%';
                    img1.style.objectFit = 'contain';
                    img1.style.borderRadius = '8px';
                    img1.style.background = 'rgba(30, 41, 59, 0.5)';
                    
                    img1.src = `data:image/jpeg;base64,${imageData.original}`;
                    img1.alt = '对比原始图像';
                    
                    if (overlay1) {
                        comparison1.insertBefore(img1, overlay1);
                    } else {
                        comparison1.appendChild(img1);
                    }
                }
                
                // 更新对比视图中的处理后图像
                if (imageData.processed && comparison2) {
                    const placeholder2 = comparison2.querySelector('.image-placeholder');
                    const overlay2 = document.getElementById('comparison-detection-2');
                    
                    if (placeholder2) {
                        placeholder2.style.display = 'none';
                    }
                    
                    const oldImg2 = comparison2.querySelector('.real-image');
                    if (oldImg2) {
                        oldImg2.remove();
                    }
                    
                    const img2 = document.createElement('img');
                    img2.className = 'real-image';
                    img2.style.width = '100%';
                    img2.style.height = '100%';
                    img2.style.objectFit = 'contain';
                    img2.style.borderRadius = '8px';
                    img2.style.background = 'rgba(30, 41, 59, 0.5)';
                    
                    img2.src = `data:image/jpeg;base64,${imageData.processed}`;
                    img2.alt = '对比处理后图像';
                    
                    if (overlay2) {
                        comparison2.insertBefore(img2, overlay2);
                    } else {
                        comparison2.appendChild(img2);
                    }
                }
                
            } catch (error) {
                console.error('更新对比视图时出错:', error);
            }
        }

                // 新增：开始运行时间计时
        function startOperationTimer() {
            if (operationStartTime === null) {
                operationStartTime = new Date();
                hasReceivedFirstEvent = true;
                
                // 启动定时器，每秒更新一次运行时间
                operationTimer = setInterval(updateOperationTime, 1000);
                
                console.log('⏱️ 运行时间计时开始');
                addLog("运行时间计时开始", "success");
            }
        }

        // 新增：停止运行时间计时
        function stopOperationTimer() {
            if (operationTimer) {
                clearInterval(operationTimer);
                operationTimer = null;
                console.log('⏱️ 运行时间计时停止');
                addLog("运行时间计时停止", "warning");
            }
        }

        // 新增：更新运行时间显示
        // 确保运行时间在状态数据表格中正确更新
        function updateOperationTime() {
            if (operationStartTime === null) {
                console.log('⏱️ 运行时间计时器未启动');
                return;
            }
            
            const now = new Date();
            const diff = now - operationStartTime; // 毫秒数
            
            // 将毫秒数转换为小时、分钟、秒
            const hours = Math.floor(diff / (1000 * 60 * 60));
            const minutes = Math.floor((diff % (1000 * 60 * 60)) / (1000 * 60));
            const seconds = Math.floor((diff % (1000 * 60)) / 1000);
            
            // 格式化为字符串
            let timeString = '';
            if (hours > 0) {
                timeString = `${hours}小时${minutes}分${seconds}秒`;
            } else if (minutes > 0) {
                timeString = `${minutes}分${seconds}秒`;
            } else {
                timeString = `${seconds}秒`;
            }
            
            console.log(`⏱️ 更新运行时间显示: ${timeString}`);
            
            // 更新状态数据表格中的运行时间
            updateStatusParameter('运行时间', timeString, '运行中', 'status-success');
            
            // 同时更新模拟数据，以便后续刷新时保持一致性
            updateMockParameter('运行时间', timeString, '运行中', 'status-success');
        }
        // 新增：重置运行时间
        function resetOperationTimer() {
            stopOperationTimer();
            operationStartTime = null;
            hasReceivedFirstEvent = false;
            
            // 重置显示
            updateStatusParameter('运行时间', '0秒', '待机', 'status-info');
            updateMockParameter('运行时间', '0秒', '待机', 'status-info');
            
            console.log('⏱️ 运行时间已重置');
            addLog("运行时间已重置", "info");
        }

                // 图像刷新函数
        function refreshImage(containerId) {
            addLog(`手动刷新 ${containerId} 的图像`, "info");
            
            // 根据容器ID确定图像类型
            if (containerId === 'image-container-1' && imageData.original) {
                displayOriginalImage(imageData.original);
            } else if (containerId === 'image-container-2' && imageData.processed) {
                displayProcessedImage(imageData.processed);
            } else if (containerId === 'comparison-container') {
                updateComparisonImages();
            }
        }

                // 在缩放控制按钮后添加刷新按钮
        function addImageRefreshControls() {
            const containers = [
                'image-container-1',
                'image-container-2', 
                'comparison-container'
            ];
            
            containers.forEach(containerId => {
                const container = document.getElementById(containerId);
                if (container) {
                    const zoomControls = container.querySelector('.zoom-controls');
                    if (zoomControls) {
                        const refreshBtn = document.createElement('button');
                        refreshBtn.className = 'zoom-btn';
                        refreshBtn.innerHTML = '<i class="fas fa-sync-alt"></i>';
                        refreshBtn.title = '刷新图像';
                        refreshBtn.onclick = function() {
                            refreshImage(containerId);
                        };
                        zoomControls.appendChild(refreshBtn);
                    }
                }
            });
        }

        // 修复后的初始化WebSocket函数
        function initWebSocket() {
            try {
                const protocol = window.location.protocol === 'https:' ? 'wss:' : 'ws:';
                const host = window.location.hostname || '10.0.0.7';
                const port = window.location.port || '7722';
                const wsUrl = `${protocol}//${host}:${port}`;
                
                console.log('🔌 连接WebSocket:', wsUrl);
                socket = io(wsUrl, {
                    transports: ['websocket', 'polling']
                });
                
                // 连接状态监听
                socket.on('connect', function() {
                    console.log('✅ WebSocket连接成功');
                    addLog("WebSocket连接已建立", "success");
                    useRealData = true;
                    isUsingRealData = true;
                    
                    // 如果之前有计时器，继续计时
                    if (hasReceivedFirstEvent && !operationTimer) {
                        startOperationTimer();
                    }
                });

                socket.on('disconnect', function() {
                    console.log('❌ WebSocket连接断开');
                    addLog("WebSocket连接已断开", "warning");
                    useRealData = false;
                    isUsingRealData = false;
                    
                    // 停止计时器
                    stopOperationTimer();
                });

                socket.on('connect_error', function(error) {
                    console.error('💥 WebSocket连接错误:', error);
                    addLog("WebSocket连接错误: " + error.message, "error");
                    useRealData = false;
                });

                // 统一的数据接收处理
                socket.on('message', function(data) {
                    console.log('📨 收到WebSocket消息:', data);
                    try {
                        const parsedData = typeof data === 'string' ? JSON.parse(data) : data;
                        handleWebSocketMessage(parsedData);
                    } catch (error) {
                        console.error('消息解析错误:', error);
                        addLog("WebSocket消息解析错误", "error");
                    }
                });

                // 专门的事件数据通道
                socket.on('ros_event_data', function(data) {
                    console.log('📢 收到ROS事件数据:', data);
                    handleEventData(data);
                });

                // 实时数据通道
                socket.on('ros_realtime_data', function(data) {
                    console.log('📊 收到实时数据:', data);
                    handleRealTimeData(data);
                });

                // 状态数据通道
                socket.on('ros_status_data', function(data) {
                    console.log('📈 收到状态数据:', data);
                    handleStatusData(data);
                });

            } catch (error) {
                console.error('WebSocket初始化失败:', error);
                addLog("WebSocket初始化失败: " + error.message, "error");
            }
        }

        // 修改 WebSocket 消息处理，确保正确识别和使用真实数据
        function handleWebSocketMessage(data) {
            console.log('📨 收到WebSocket消息:', data);
            try {
                const parsedData = typeof data === 'string' ? JSON.parse(data) : data;
                
                // 标记为真实数据
                useRealData = true;
                isUsingRealData = true;
                realDataStatus.lastRealDataTime = new Date();
                
                if (parsedData.type && (parsedData.type === 'image_show' || parsedData.type === 'image_detection')) {
                    console.log('🖼️ 识别为图像数据');
                    handleEventData(parsedData);
                    return;
                }

                // 根据数据类型路由处理
                if (parsedData.type === 'status' || parsedData.data_type === 'status' || isStatusData(parsedData)) {
                    console.log('📊 识别为状态数据');
                    handleStatusData(parsedData);
                    realDataStatus.status = true;
                    return;
                } else if (parsedData.type === 'event' || parsedData.event_type) {
                    console.log('📢 识别为事件数据');
                    handleEventData(parsedData);
                    return;
                } else if (parsedData.type === 'realtime' || parsedData.data_type === 'realtime') {
                    console.log('🔄 识别为实时数据');
                    handleRealTimeData(parsedData);
                    return;
                } else if (parsedData.x !== undefined || parsedData.position_x !== undefined) {
                    // 推断为位置数据
                    console.log('🎯 推断为位置数据');
                    realDataStatus.endEffector = true;
                    updateRealEndPose(parsedData);
                    return;
                } else if (typeof parsedData === 'object') {
                    // 如果没有明确类型，但包含状态相关字段，当作状态数据处理
                    const statusKeys = ['status', 'battery', 'temperature', 'error_code', 'current_point_id'];
                    if (statusKeys.some(key => parsedData[key] !== undefined)) {
                        console.log('🔍 推断为状态数据（通过字段匹配）');
                        realDataStatus.status = true;
                        handleStatusData(parsedData);
                    } else {
                        console.log('❓ 未知数据类型，尝试通用处理:', parsedData);
                        handleEventData(parsedData);
                    }
                } else {
                    console.log('❓ 未知数据类型，尝试作为事件处理:', parsedData);
                    handleEventData(parsedData);
                }
                
            } catch (error) {
                console.error('消息解析错误:', error);
                addLog("WebSocket消息解析错误", "error");
            }
        }

        function isStatusData(data) {
            if (!data || typeof data !== 'object') return false;
            
            // 检查是否包含典型的状态字段
            const statusFields = ['running_status', 'battery', 'temperature', 'success_count', 'error_code'];
            const dataToCheck = data.data || data;
            
            return statusFields.some(field => field in dataToCheck);
        }

        function handleStatusData(data) {
            console.log('📋 处理状态数据:', data);
            
            let statusData = [];
            
            // 多种数据格式支持
            if (data.data && typeof data.data === 'object') {
                // 格式1: 数据在 data.data 中
                statusData = formatStatusDataFromObject(data.data);
            } else if (typeof data === 'object') {
                // 格式2: 数据本身就是状态对象
                statusData = formatStatusDataFromObject(data);
            } else {
                // 使用模拟数据作为后备
                statusData = mockStatusData;
            }
            
            updateStatusData(statusData);
        }

                // 新增：更新总点数的函数
        function updateTotalPoints(totalPoints, status = '完成') {
            if (totalPoints === undefined || totalPoints === null) return;
            
            const totalPointsValue = String(totalPoints);
            let statusClass = 'status-success';
            
            // 根据状态设置显示样式
            if (status === '移动中') {
                statusClass = 'status-warning';
            } else if (status === '完成') {
                statusClass = 'status-success';
            } else {
                statusClass = 'status-info';
            }
            
            // 更新状态数据表格中的总点数
            updateStatusParameter('总点数', totalPointsValue, status, statusClass);
            
            // 同时更新模拟数据，以便后续刷新时保持一致性
            updateMockParameter('总点数', totalPointsValue, status, statusClass);
            
            console.log(`📊 总点数更新: ${totalPointsValue}, 状态: ${status}`);
        }

        // 新增：更新成功率的函数
        function updateSuccessRate(successCount, totalCount) {
            if (successCount === undefined || totalCount === undefined || totalCount === 0) return;
            
            const successRate = (successCount / totalCount) * 100;
            const successRateValue = `${successRate.toFixed(1)}%`;
            
            let status, statusClass;
            
            // 根据成功率设置状态
            if (successRate >= 90) {
                status = '优秀';
                statusClass = 'status-success';
            } else if (successRate >= 60) {
                status = '良好';
                statusClass = 'status-success';
            } else {
                status = '差';
                statusClass = 'status-error';
            }
            
            // 更新状态数据表格中的成功率
            updateStatusParameter('成功率', successRateValue, status, statusClass);
            
            // 同时更新模拟数据，以便后续刷新时保持一致性
            updateMockParameter('成功率', successRateValue, status, statusClass);
            
            console.log(`📈 成功率更新: ${successRateValue}, 状态: ${status}`);
        }

        // 新增：更新成功点数的函数（同时更新成功率）
        function updateSuccessPoints(successCount, totalCount, status = '良好') {
            if (successCount === undefined || totalCount === undefined) return;
            
            const successPointsValue = `${successCount}/${totalCount}`;
            let statusClass = 'status-success';
            
            // 根据状态设置显示样式
            if (status === '移动中') {
                statusClass = 'status-warning';
            } else if (status === '完成') {
                statusClass = 'status-success';
            } else {
                statusClass = 'status-info';
            }
            
            // 更新状态数据表格中的成功点数
            updateStatusParameter('成功点数', successPointsValue, status, statusClass);
            
            // 同时更新模拟数据，以便后续刷新时保持一致性
            updateMockParameter('成功点数', successPointsValue, status, statusClass);
            
            // 同时更新成功率
            updateSuccessRate(successCount, totalCount);
            
            console.log(`✅ 成功点数更新: ${successPointsValue}, 状态: ${status}`);
        }

                // 通用函数：更新状态数据表格中的参数
        function updateStatusParameter(parameterName, value, status, statusClass) {
            const tbody = document.querySelector('#status-data-table tbody');
            if (!tbody) {
                console.warn(`状态数据表格tbody未找到，无法更新 ${parameterName}`);
                return;
            }
            
            const rows = tbody.querySelectorAll('tr');
            let parameterFound = false;
            
            for (let row of rows) {
                const cells = row.querySelectorAll('td');
                if (cells.length >= 2 && cells[0].textContent === parameterName) {
                    // 更新值
                    cells[1].textContent = value;
                    
                    // 更新状态徽章
                    if (cells.length >= 3) {
                        const statusBadge = cells[2].querySelector('.status-badge');
                        if (statusBadge) {
                            statusBadge.textContent = status;
                            statusBadge.className = `status-badge ${statusClass}`;
                        }
                    }
                    parameterFound = true;
                    console.log(`✅ 更新 ${parameterName}: ${value}`);
                    break;
                }
            }
            
            if (!parameterFound) {
                console.warn(`❌ 未找到参数行: ${parameterName}`);
            }
        }

        // 通用函数：更新模拟数据中的参数
        function updateMockParameter(parameterName, value, status, statusClass) {
            for (let item of mockStatusData) {
                if (item.parameter === parameterName) {
                    item.value = value;
                    item.status = status;
                    item.statusClass = statusClass;
                    break;
                }
            }
        }

        function formatStatusDataFromObject(statusObj) {
            const statusMap = {
                // 运行状态相关
                'running_status': { name: '运行状态', type: 'status' },
                'status': { name: '运行状态', type: 'status' },
                'control_mode': { name: '控制模式', type: 'text' },
                'operation_mode': { name: '操作模式', type: 'text' },
                
                // 任务进度相关
                'success_count': { name: '成功点数', type: 'count' },
                'total_count': { name: '总点数', type: 'count' },
                'current_point_id': { name: '当前点ID', type: 'id' },
                'completion_rate': { name: '完成率', type: 'percentage' },
                
                // 系统状态相关
                'battery': { name: '电池电量', type: 'percentage' },
                'battery_level': { name: '电池电量', type: 'percentage' },
                'temperature': { name: '系统温度', type: 'temperature' },
                'system_temp': { name: '系统温度', type: 'temperature' },
                'operation_time': { name: '运行时间', type: 'time' },
                'uptime': { name: '运行时间', type: 'time' },
                
                // 网络相关
                'network_delay': { name: '网络延迟', type: 'delay' },
                'latency': { name: '网络延迟', type: 'delay' },
                
                // 机械臂状态相关
                'load_status': { name: '负载状态', type: 'weight' },
                'load': { name: '负载状态', type: 'weight' },
                'error_code': { name: '错误代码', type: 'error' },
                'fault_code': { name: '错误代码', type: 'error' }
            };
            
            const formattedData = [];
        
            for (const [key, value] of Object.entries(statusObj)) {
                const mapping = statusMap[key];
                if (mapping) {
                    let displayValue = value;
                    let status = '正常';
                    let statusClass = 'status-success';
                    
                    // 根据数据类型格式化值和状态
                    switch(mapping.type) {
                        case 'percentage':
                            displayValue = typeof value === 'number' ? `${value}%` : value;
                            status = value > 20 ? '良好' : '低电量';
                            statusClass = value > 20 ? 'status-success' : 'status-warning';
                            break;
                            
                        case 'temperature':
                            displayValue = typeof value === 'number' ? `${value}°C` : value;
                            status = value < 50 ? '正常' : value < 65 ? '注意' : '过高';
                            statusClass = value < 50 ? 'status-success' : value < 65 ? 'status-warning' : 'status-error';
                            break;
                            
                        case 'count':
                            // 如果是成功点数/总点数的格式
                            if (key === 'success_count' && statusObj.total_count !== undefined) {
                                displayValue = `${value}/${statusObj.total_count}`;
                                const rate = statusObj.total_count > 0 ? (value / statusObj.total_count) * 100 : 0;
                                status = rate > 80 ? '良好' : rate > 60 ? '一般' : '较差';
                                statusClass = rate > 80 ? 'status-success' : rate > 60 ? 'status-warning' : 'status-error';
                            } else {
                                displayValue = String(value);
                            }
                            break;
                            
                        case 'error':
                            status = value === '0x0000' || value === 0 ? '无错误' : '有错误';
                            statusClass = value === '0x0000' || value === 0 ? 'status-success' : 'status-error';
                            break;
                            
                        case 'delay':
                            displayValue = typeof value === 'number' ? `${value}ms` : value;
                            status = value < 50 ? '良好' : value < 100 ? '一般' : '较差';
                            statusClass = value < 50 ? 'status-success' : value < 100 ? 'status-warning' : 'status-error';
                            break;
                            
                        case 'status':
                            status = value === 'moving' || value === 'running' ? '运行中' : 
                                    value === 'idle' ? '待机' : 
                                    value === 'error' ? '错误' : String(value);
                            statusClass = value === 'moving' || value === 'running' ? 'status-success' :
                                        value === 'idle' ? 'status-info' :
                                        value === 'error' ? 'status-error' : 'status-info';
                            break;
                            
                        case 'id':
                            status = value > 0 ? '进行中' : '待命';
                            statusClass = value > 0 ? 'status-warning' : 'status-info';
                            break;
                        
                        default:
                            displayValue = String(value);
                    }
                    
                    formattedData.push({
                        parameter: mapping.name,
                        value: displayValue,
                        status: status,
                        statusClass: statusClass
                    });
                }
            }
            
            // 如果格式化后没有数据，使用模拟数据
            if (formattedData.length === 0) {
                return mockStatusData;
            }
            
            return formattedData;
        }

        function formatStatusValue(value, type, key) {
            let displayValue = String(value);
            let status = '正常';
            let statusClass = 'status-success';
            
            switch (type) {
                case 'percentage':
                    const percent = parseFloat(value);
                    if (percent < 20) {
                        status = '危险';
                        statusClass = 'status-error';
                    } else if (percent < 50) {
                        status = '警告';
                        statusClass = 'status-warning';
                    } else {
                        status = '良好';
                        statusClass = 'status-success';
                    }
                    displayValue = percent.toFixed(1);
                    break;
                    
                case 'temperature':
                    const temp = parseFloat(value);
                    if (temp > 70) {
                        status = '过高';
                        statusClass = 'status-error';
                    } else if (temp > 50) {
                        status = '注意';
                        statusClass = 'status-warning';
                    } else {
                        status = '正常';
                        statusClass = 'status-success';
                    }
                    displayValue = temp.toFixed(1);
                    break;
                    
                case 'progress':
                    // 处理 "成功点数" 这样的进度显示
                    if (typeof value === 'string' && value.includes('/')) {
                        const parts = value.split('/');
                        const current = parseInt(parts[0]);
                        const total = parseInt(parts[1]);
                        const rate = total > 0 ? (current / total) * 100 : 0;
                        
                        if (rate === 100) {
                            status = '完成';
                            statusClass = 'status-success';
                        } else if (rate > 70) {
                            status = '良好';
                            statusClass = 'status-success';
                        } else if (rate > 30) {
                            status = '进行中';
                            statusClass = 'status-warning';
                        } else {
                            status = '开始';
                            statusClass = 'status-info';
                        }
                    }
                    break;
                    
                case 'code':
                    if (value !== '0' && value !== '0x0000' && value !== '无错误') {
                        status = '异常';
                        statusClass = 'status-error';
                    }
                    break;
                    
                case 'string':
                    if (key.includes('error') || key.includes('fault')) {
                        if (value && value !== '正常' && value !== '无错误') {
                            status = '异常';
                            statusClass = 'status-error';
                        }
                    } else if (key.includes('status')) {
                        if (value.includes('错误') || value.includes('异常') || value.includes('停止')) {
                            status = '异常';
                            statusClass = 'status-error';
                        } else if (value.includes('警告') || value.includes('注意')) {
                            status = '警告';
                            statusClass = 'status-warning';
                        } else if (value.includes('运行') || value.includes('正常')) {
                            status = '正常';
                            statusClass = 'status-success';
                        }
                    }
                    break;
            }
            
            return { displayValue, status, statusClass };
        }

        // 修改：更新当前点坐标的函数，支持保持现有值
        function updateCurrentPointCoordinate(pointData) {
            if (!pointData) return;
            
            let coordinateValue;
            let coordinateStatus = '待命';
            let statusClass = 'status-info';
            
            // 如果指定了保持现有值，则使用现有值
            if (pointData.preserveValue) {
                coordinateValue = pointData.preserveValue;
            } else if (pointData.world_coord) {
                // 否则使用新的坐标值
                const coord = pointData.world_coord;
                const x = parseFloat(coord.x) || 0;
                const y = parseFloat(coord.y) || 0;
                coordinateValue = `X: ${x.toFixed(3)}, Y: ${y.toFixed(3)}`;
            } else {
                // 如果没有坐标数据，保持现有值
                const tbody = document.querySelector('#status-data-table tbody');
                if (tbody) {
                    const rows = tbody.querySelectorAll('tr');
                    for (let row of rows) {
                        const cells = row.querySelectorAll('td');
                        if (cells.length >= 2 && cells[0].textContent === '当前点坐标') {
                            coordinateValue = cells[1].textContent;
                            break;
                        }
                    }
                }
            }
            
            // 根据移动状态设置显示状态
            if (pointData.is_moving) {
                coordinateStatus = '移动中';
                statusClass = 'status-warning';
            } else if (pointData.is_completed) {
                coordinateStatus = '完成';
                statusClass = 'status-success';
            }
            
            // 更新状态数据表格中的当前点坐标
            updateStatusCoordinate(coordinateValue, coordinateStatus, statusClass);
            
            // 同时更新模拟数据，以便后续刷新时保持一致性
            updateMockCoordinate(coordinateValue, coordinateStatus, statusClass);
            
            console.log(`📍 当前点坐标更新: ${coordinateValue}, 状态: ${coordinateStatus}`);
        }

        // 新增：更新状态数据表格中的当前点坐标
        function updateStatusCoordinate(value, status, statusClass) {
            const tbody = document.querySelector('#status-data-table tbody');
            if (!tbody) return;
            
            const rows = tbody.querySelectorAll('tr');
            for (let row of rows) {
                const cells = row.querySelectorAll('td');
                if (cells.length >= 2 && cells[0].textContent === '当前点坐标') {
                    // 更新值
                    cells[1].textContent = value;
                    
                    // 更新状态徽章
                    if (cells.length >= 3) {
                        const statusBadge = cells[2].querySelector('.status-badge');
                        if (statusBadge) {
                            statusBadge.textContent = status;
                            statusBadge.className = `status-badge ${statusClass}`;
                        }
                    }
                    break;
                }
            }
        }

        // 新增：更新模拟数据中的当前点坐标
        function updateMockCoordinate(value, status, statusClass) {
            for (let item of mockStatusData) {
                if (item.parameter === '当前点坐标') {
                    item.value = value;
                    item.status = status;
                    item.statusClass = statusClass;
                    break;
                }
            }
        }

        // 更新状态数据表格
        function updateStatusData(statusData) {
            const tbody = document.querySelector('#status-data-table tbody');
            if (!tbody) {
                console.error('状态数据表格tbody未找到');
                return;
            }
            
            tbody.innerHTML = '';

            if (Array.isArray(statusData) && statusData.length > 0) {
                statusData.forEach(item => {
                    const row = document.createElement('tr');
                    row.innerHTML = `
                        <td>${item.parameter || '未知参数'}</td>
                        <td>${item.value || 'N/A'}</td>
                        <td><span class="status-badge ${item.statusClass || 'status-info'}">${item.status || '未知'}</span></td>
                    `;
                    tbody.appendChild(row);
                });
            } else {
                // 如果没有数据，显示提示
                const row = document.createElement('tr');
                row.innerHTML = `
                    <td colspan="3" style="text-align: center; color: var(--text-muted);">
                        <i class="fas fa-exclamation-circle"></i> 暂无状态数据
                    </td>
                `;
                tbody.appendChild(row);
            }
            
            // 添加调试日志
            console.log('✅ 状态数据已更新，条目数:', statusData.length);
        }

        function startStatusMonitoring() {
            setInterval(() => {
                // 如果使用真实数据，尝试请求状态更新
                if (useRealData && socket && socket.connected) {
                    socket.emit('request_status');
                } else {
                    // 否则使用模拟数据更新
                    simulateStatusUpdate();
                }
            }, 5000); // 每5秒更新一次
        }

        function simulateStatusUpdate() {
            if (useRealData) return;
            
            // 随机更新模拟数据
            mockStatusData.forEach(item => {
                if (item.parameter === '成功点数') {
                    const [success, total] = item.value.split('/');
                    const newSuccess = Math.min(parseInt(success) + Math.floor(Math.random() * 2), parseInt(total));
                    item.value = `${newSuccess}/${total}`;
                    item.status = newSuccess === parseInt(total) ? '完成' : '进行中';
                    item.statusClass = newSuccess === parseInt(total) ? 'status-success' : 'status-warning';
                }
                
                if (item.parameter === '系统温度') {
                    const temp = parseInt(item.value);
                    const newTemp = temp + Math.floor(Math.random() * 3) - 1; // -1, 0, 1
                    item.value = `${Math.max(35, Math.min(55, newTemp))}°C`;
                }
                
                if (item.parameter === '电池电量') {
                    const battery = parseInt(item.value);
                    const newBattery = battery - Math.floor(Math.random() * 2);
                    item.value = `${Math.max(10, newBattery)}%`;
                    item.status = newBattery > 30 ? '良好' : '注意';
                    item.statusClass = newBattery > 30 ? 'status-success' : 'status-warning';
                }
            });
            
            updateStatusData(mockStatusData);
        }

        // 更新位置数据表格
        function updatePositionData(positionData) {
            const tbody = document.querySelector('#position-data-table tbody');
            if (!tbody) {
                console.warn('位置数据表格tbody未找到');
                return;
            }
            
            // 如果是单个对象，转换为数组
            if (!Array.isArray(positionData)) {
                positionData = [positionData];
            }
            
            tbody.innerHTML = '';

            positionData.forEach(item => {
                const row = document.createElement('tr');
                row.innerHTML = `
                    <td>${item.timestamp || new Date().toLocaleTimeString()}</td>
                    <td>${(item.x || 0).toFixed(6)}</td>
                    <td>${(item.y || 0).toFixed(6)}</td>
                    <td>${(item.z || 0).toFixed(6)}</td>
                    <td>${(item.rx || 0).toFixed(2)}</td>
                    <td>${(item.ry || 0).toFixed(2)}</td>
                    <td>${(item.rz || 0).toFixed(2)}</td>
                `;
                tbody.appendChild(row);
            });
        }

        // 在WebSocket连接部分添加更详细的数据处理
        socket.on('ros_realtime_data', function(data) {
            console.log('📊 收到实时数据:', data);
            handleRealTimeData({...data, data_type: 'realtime'});
        });

        socket.on('ros_status_data', function(data) {
            console.log('📈 收到状态数据:', data);
            handleRealTimeData({...data, data_type: 'status'});
        });

        function updateCurrentPose(pose) {
            try {
                // 确保pose是对象
                if (!pose || typeof pose !== 'object') {
                    console.warn('updateCurrentPose: 无效的pose数据', pose);
                    return;
                }
                
                currentPose = { ...currentPose, ...pose };
                
                // 安全地更新显示元素
                const updateElement = (id, value, precision = 3) => {
                    const element = document.getElementById(id);
                    if (element) {
                        element.textContent = typeof value === 'number' ? value.toFixed(precision) : String(value || 0);
                    }
                };
                
                updateElement('current-pose-x', pose.x, 3);
                updateElement('current-pose-y', pose.y, 3);
                updateElement('current-pose-z', pose.z, 3);
                updateElement('current-pose-rx', pose.rx, 2);
                updateElement('current-pose-ry', pose.ry, 2);
                updateElement('current-pose-rz', pose.rz, 2);
                
            } catch (error) {
                console.error('更新当前姿态时出错:', error);
                addLog('更新姿态数据时出错: ' + error.message, "error");
            }
        }

        function testDataUpdate() {
            console.log('🧪 测试数据更新...');
            
            // 创建测试数据
            const testPose = {
                x: 1.234 + Math.random() * 0.1 - 0.05,
                y: 2.345 + Math.random() * 0.1 - 0.05,
                z: 0.123 + Math.random() * 0.05 - 0.025,
                rx: (Math.random() - 0.5) * 20,
                ry: (Math.random() - 0.5) * 20,
                rz: (Math.random() - 0.5) * 20,
                timestamp: new Date().toLocaleTimeString()
            };
            
            console.log('测试数据:', testPose);
            updateCurrentPose(testPose);
            updatePositionData([testPose]);
            addLog(`测试数据更新: X=${testPose.x.toFixed(3)}, Y=${testPose.y.toFixed(3)}`, "success");
        }

        // 在页面加载完成后添加测试按钮（临时调试用）
        document.addEventListener('DOMContentLoaded', function() {
            // 添加测试按钮到控制面板
            const controlPanel = document.querySelector('.control-panel');
            if (controlPanel) {
                const testBtn = document.createElement('button');
                testBtn.className = 'control-btn';
                testBtn.innerHTML = `
                    <i class="fas fa-vial"></i>
                    <span class="btn-text">测试数据</span>
                `;
                testBtn.onclick = testDataUpdate;
                controlPanel.appendChild(testBtn);
            }
            
            // 初始化时显示一些测试数据
            setTimeout(() => {
                const initialPose = {
                    x: 1.234567,
                    y: 2.345678, 
                    z: 0.123456,
                    rx: 5.67,
                    ry: -3.45,
                    rz: 12.34
                };
                updateCurrentPose(initialPose);
            }, 1000);
            updateStatusParameter('运行时间', '0秒', '待机', 'status-info');
        });

        // 更新关节数据表格显示
        // 修改 updateJointsData 函数，支持电流显示
        function updateJointsData(jointsData) {
            const tbody = document.querySelector('#joints-data-table tbody');
            if (!tbody) {
                console.warn('关节数据表格tbody未找到');
                return;
            }
            
            tbody.innerHTML = '';

            if (Array.isArray(jointsData) && jointsData.length > 0) {
                jointsData.forEach(item => {
                    const row = document.createElement('tr');
                    row.innerHTML = `
                        <td>${item.joint}</td>
                        <td>${item.angle}</td>
                        <td>${item.speed}</td>
                        <td>${item.torque}</td>
                        <td>${item.current || '0.00'}</td> <!-- 电流列 -->
                        <td>${item.temperature}</td>
                    `;
                    tbody.appendChild(row);
                });
                
                console.log(`✅ 关节数据表格已更新，显示 ${jointsData.length} 个关节`);
            } else {
                // 如果没有数据，显示提示
                const row = document.createElement('tr');
                row.innerHTML = `
                    <td colspan="6" style="text-align: center; color: var(--text-muted);">
                        <i class="fas fa-exclamation-circle"></i> 暂无关节数据
                    </td>
                `;
                tbody.appendChild(row);
                console.log('⚠️ 关节数据为空，显示提示信息');
            }
        }

                // 新增：专门处理关节电流数据的函数
        function updateJointCurrents(currentData) {
            console.log('⚡ 更新关节电流数据:', currentData);
            
            if (!currentData || !currentData.currents || !Array.isArray(currentData.currents)) {
                console.warn('无效的关节电流数据格式');
                return;
            }
            
            const currents = currentData.currents;
            jointCurrents = currents; // 存储电流数据
            
            // 更新关节数据表格中的电流值
            updateJointsTableWithCurrents(currents);
            
            // 添加日志
            addLog(`关节电流更新: ${currents.map(c => c?.toFixed(2) || '0.00').join(', ')} A`, "info");
        }

        // 新增：使用电流数据更新关节表格
        function updateJointsTableWithCurrents(currents) {
            const tbody = document.querySelector('#joints-data-table tbody');
            if (!tbody) return;
            
            const rows = tbody.querySelectorAll('tr');
            
            rows.forEach((row, index) => {
                const cells = row.querySelectorAll('td');
                if (cells.length >= 5 && currents[index] !== undefined) {
                    // 更新电流列（第5列，索引为4）
                    cells[4].textContent = currents[index].toFixed(2);
                    
                    // 根据电流值添加颜色提示
                    const currentValue = currents[index];
                    if (currentValue > 1.5) {
                        cells[4].style.color = 'var(--accent-red)';
                        cells[4].style.fontWeight = 'bold';
                    } else if (currentValue > 1.0) {
                        cells[4].style.color = 'var(--accent-orange)';
                    } else {
                        cells[4].style.color = 'var(--accent-green)';
                    }
                }
            });
        }

        // 新增：处理关节状态数据（包含位置、速度、扭矩）
        function handleJointStatesData(jointData) {
            console.log('🦾 处理关节状态数据:', jointData);
            
            if (!jointData || !jointData.data) {
                console.warn('无效的关节状态数据');
                return;
            }
            
            const data = jointData.data;
            const positions = data.positions || [];
            const velocities = data.velocities || [];
            const efforts = data.efforts || []; // 扭矩数据
            const names = data.names || [];
            
            // 构建关节数据显示数据
            const jointsDisplayData = positions.map((position, index) => {
                const jointName = names[index] || `关节${index + 1}`;
                const velocity = velocities[index] || 0;
                const torque = efforts[index] || 0;
                const current = jointCurrents[index] || 0; // 使用存储的电流数据
                
                return {
                    joint: jointName,
                    angle: position.toFixed(3),
                    speed: velocity.toFixed(3),
                    torque: torque.toFixed(2),
                    current: current.toFixed(2),
                    temperature: '0' // 温度数据需要从其他来源获取
                };
            });
            
            // 更新显示
            updateJointsData(jointsDisplayData);
            
            console.log(`✅ 关节状态数据更新完成，处理 ${positions.length} 个关节`);
        }

        // 更新传感器数据表格
        function updateSensorsData(sensorsData) {
            const tbody = document.querySelector('#sensors-data-table tbody');
            tbody.innerHTML = '';

            sensorsData.forEach(item => {
                const row = document.createElement('tr');
                row.innerHTML = `
                    <td>${item.sensor}</td>
                    <td>${item.type}</td>
                    <td>${item.value}</td>
                    <td>${item.unit}</td>
                    <td><span class="status-badge ${item.statusClass || 'status-info'}">${item.status}</span></td>
                `;
                tbody.appendChild(row);
            });
        }

        // 修改 handleRealTimeData 函数，强制使用真实数据
        function handleRealTimeData(data) {
            if (!data) return;
            
            console.log('🔄 处理实时数据:', data);
            
            // 强制标记为真实数据
            useRealData = true;
            isUsingRealData = true;
            realDataStatus.lastRealDataTime = new Date();
            
            // 专门处理末端位置数据
            if (data.data && data.data.end_effector_position) {
                console.log('🎯 实时数据中包含末端位置');
                realDataStatus.endEffector = true;
                updateRealEndPose(data);
                return;
            }
            
            if (data.end_effector_position) {
                console.log('🎯 直接末端位置数据');
                realDataStatus.endEffector = true;
                updateRealEndPose(data);
                return;
            }
            
            // 处理关节数据
            if (data.data && (data.data.joint_states || data.data.joint_currents)) {
                console.log('🦾 实时数据中包含关节数据');
                realDataStatus.joints = true;
                
                if (data.data.joint_states) {
                    handleJointStatesData({ data: data.data.joint_states });
                }
                if (data.data.joint_currents) {
                    updateJointCurrents(data.data.joint_currents);
                }
                return;
            }
            
            // 尝试推断数据类型
            if (data.x !== undefined || data.position_x !== undefined) {
                console.log('🔍 推断为位置数据');
                realDataStatus.endEffector = true;
                updateRealEndPose(data);
                return;
            }
            
            // 根据数据类型分发处理
            switch(data.type) {
                case 'joint_data':
                case 'joints':
                    realDataStatus.joints = true;
                    updateRealJoints(data);
                    break;
                case 'sensors':
                    updateRealSensors(data);
                    break;
                default:
                    console.log('📝 实时数据无匹配类型，使用状态更新:', data);
                    realDataStatus.status = true;
                    handleStatusData(data);
            }
        }

        function updateRealJoints(data) {
            console.log('🦾 更新实时关节数据:', data);
            
            // 尝试处理关节状态数据
            if (data.data && data.data.positions) {
                handleJointStatesData(data);
            } 
            // 尝试处理关节电流数据
            else if (data.data && data.data.currents) {
                updateJointCurrents(data.data);
            }
            // 如果是通用关节数据格式
            else if (data.positions || data.currents) {
                if (data.positions) {
                    handleJointStatesData({ data: data });
                }
                if (data.currents) {
                    updateJointCurrents(data);
                }
            } else {
                console.log('❌ 无法识别的关节数据格式');
            }
        }

        function updateRealSensors(data) {
            console.log('📡 更新传感器数据:', data);
            
            let sensorsData = [];
            
            if (data.data && typeof data.data === 'object') {
                sensorsData = Object.keys(data.data).map(key => {
                    const value = data.data[key];
                    let status = '正常';
                    let statusClass = 'status-success';
                    
                    if (typeof value === 'number') {
                        if (key.includes('temp') || key.includes('temperature')) {
                            status = value > 60 ? '过高' : value > 45 ? '注意' : '正常';
                            statusClass = value > 60 ? 'status-error' : value > 45 ? 'status-warning' : 'status-success';
                        }
                    }
                    
                    return {
                        sensor: key,
                        type: getSensorType(key),
                        value: String(value),
                        unit: getSensorUnit(key),
                        status: status,
                        statusClass: statusClass
                    };
                });
            } else {
                // 使用模拟数据
                sensorsData = mockSensorsData;
            }
            
            updateSensorsData(sensorsData);
        }

        function getSensorType(sensorName) {
            const typeMap = {
                'temperature': '温度',
                'force': '力反馈',
                'vision': '图像',
                'distance': '距离',
                'humidity': '湿度',
                'collision': '安全'
            };
            
            for (const [key, value] of Object.entries(typeMap)) {
                if (sensorName.toLowerCase().includes(key)) {
                    return value;
                }
            }
            
            return '未知';
        }

        // 辅助函数：获取传感器单位
        function getSensorUnit(sensorName) {
            const unitMap = {
                'temperature': '°C',
                'force': 'N',
                'vision': '像素',
                'distance': 'm',
                'humidity': '%',
                'collision': '次'
            };
            
            for (const [key, value] of Object.entries(unitMap)) {
                if (sensorName.toLowerCase().includes(key)) {
                    return value;
                }
            }
            
            return '单位';
        }

        function handleJointData(data) {
            console.log('🦾 处理关节专用数据:', data);
            
            if (!data || !data.data || !Array.isArray(data.data.positions)) {
                console.log('❌ 无效的关节数据格式');
                return;
            }
            
            const jointData = data.data;
            const positions = jointData.positions;
            const velocities = jointData.velocities || [];
            const efforts = jointData.efforts || [];
            const names = jointData.names || [];
            
            console.log(`✅ 处理 ${positions.length} 个关节的位置数据`);
            
            // 构建关节数据显示数据
            const jointsData = positions.map((position, index) => ({
                joint: names[index] || `关节${index + 1}`,
                angle: position.toFixed(3),
                speed: velocities[index] ? velocities[index].toFixed(3) : '0.000',
                torque: efforts[index] ? efforts[index].toFixed(2) : '0.00',
                temperature: '0'
            }));
            
            // 更新显示
            updateJointsData(jointsData);
            
            console.log('✅ 关节数据更新完成');
        }

        // 修改 handleEventData 函数，标记真实数据
        function handleEventData(eventData) {
            if (!eventData) {
                console.warn('事件数据为空');
                return;
            }
            
            console.log('📨 收到事件数据:', eventData);
            
            // 标记为真实数据
            useRealData = true;
            isUsingRealData = true;
            realDataStatus.lastRealDataTime = new Date();
            
            // 启动运行时间计时（如果是第一个事件）
            if (!hasReceivedFirstEvent) {
                console.log('⏱️ 收到第一个事件，启动运行时间计时');
                startOperationTimer();
            }
            
            // 多种数据格式支持
            let eventType, eventPayload;
            
            // 格式1: 包含 data 字段的格式
            if (eventData.data && typeof eventData.data === 'object') {
                // 检查是否在 data.data 中有 type（嵌套格式）
                if (eventData.data.type) {
                    eventType = eventData.data.type;
                    eventPayload = eventData.data.data || eventData.data;
                } else {
                    // 否则使用外部的 type
                    eventType = eventData.type || 'unknown';
                    eventPayload = eventData.data;
                }
            } 
            // 格式2: 直接包含 type 和 data 的格式
            else if (eventData.type) {
                eventType = eventData.type;
                eventPayload = eventData.data || eventData;
            }
            // 格式3: 可能是简化的格式
            else {
                eventType = 'unknown';
                eventPayload = eventData;
            }
            
            console.log(`📝 识别事件类型: ${eventType}`, eventPayload);
            
            // 根据事件类型标记相应的真实数据状态
            switch(eventType) {
                case 'end_effector_position':
                    realDataStatus.endEffector = true;
                    break;
                case 'joint_states':
                case 'joint_currents':
                    realDataStatus.joints = true;
                    break;
                case 'status':
                case 'operation_statistics':
                    realDataStatus.status = true;
                    break;
            }
            
            // 根据事件类型更新运行状态
            updateRunningStatus(eventType, eventPayload);
            
            // 根据事件类型分发处理
            switch(eventType) {
                case 'joint_states':
                    console.log('🦾 处理关节状态数据');
                    realDataStatus.joints = true;
                    updateRealJoints(eventData);
                    break;
                    
                case 'joint_currents':
                    console.log('🦾 处理关节电流数据');
                    realDataStatus.joints = true;
                    updateRealJoints(eventData);
                    break;
                    
                case 'arm_stop':
                case 'arm_status_event':
                    console.log('🛑 处理机械臂停止事件');
                    realDataStatus.status = true;
                    formatArmStopEvent(eventPayload);
                    // 添加日志记录
                    addLog(`紧急事件: ${eventPayload.original_message || '机械臂状态变化'}`, "error");
                    break;
                    
                case 'detection_result':
                    console.log('👁️ 处理检测结果事件');
                    realDataStatus.status = true;
                    formatDetectionEvent(eventPayload);
                    // 添加日志记录
                    const total = eventPayload.total_positions || 0;
                    const validUseful = eventPayload.valid_useful_points || 0;
                    addLog(`检测事件: 检测到${validUseful}个有用点，总共${total}个位置`, "info");
                    break;
                    
                case 'move_complete':
                    console.log('✅ 处理移动完成事件');
                    realDataStatus.status = true;
                    formatMoveCompleteEvent(eventPayload);
                    // 添加日志记录
                    const success = eventPayload.success;
                    const moveMessage = eventPayload.message || '移动操作完成';
                    addLog(`移动完成: ${moveMessage} - ${success ? '成功' : '失败'}`, success ? "success" : "error");
                    break;
                    
                case 'fire_status':
                    console.log('🔥 处理发射状态事件');
                    realDataStatus.status = true;
                    formatFireStatusEvent(eventPayload);
                    // 添加日志记录
                    addLog(`发射状态: ${eventPayload.status}`, "info");
                    break;
                    
                case 'move_point':
                    console.log('📍 处理移动点事件');
                    realDataStatus.status = true;
                    formatMovePointEvent(eventPayload);
                    // 添加日志记录
                    const pointId = eventPayload.point_id || '未知';
                    addLog(`移动事件: 移动到目标点 ID: ${pointId}`, "info");
                    break;
                    
                case 'move_status':
                    console.log('📊 处理移动状态事件');
                    realDataStatus.status = true;
                    formatMoveStatusEvent(eventPayload);
                    // 添加日志记录
                    const currentPointId = eventPayload.current_point_id || '未知';
                    const successCount = eventPayload.success_count || 0;
                    const totalCount = eventPayload.total_count || 0;
                    const rate = eventPayload.completion_rate || 0;
                    addLog(`移动状态: 点${currentPointId} - 进度 ${successCount}/${totalCount} (${rate.toFixed(1)}%)`, "info");
                    break;
                    
                case 'move_info':
                case 'move_info_basic':
                    console.log('📋 处理移动信息事件');
                    realDataStatus.status = true;
                    formatMoveInfoEvent(eventPayload);
                    // 添加日志记录
                    const overallMessage = eventPayload.overall_message || '任务执行';
                    const overallSuccess = eventPayload.overall_success;
                    addLog(`移动信息: ${overallMessage} - ${overallSuccess ? '成功' : '失败'}`, overallSuccess ? "success" : "error");
                    break;
                    
                case 'end_effector_position':
                    console.log('🎯 处理末端位置事件');
                    realDataStatus.endEffector = true;
                    formatEndEffectorEvent(eventPayload);
                    break;
                    
                case 'operation_statistics':
                    console.log('📈 处理运行统计事件');
                    realDataStatus.status = true;
                    formatOperationStatsEvent(eventPayload);
                    // 添加日志记录
                    const successRate = eventPayload.success_rate || 0;
                    addLog(`运行统计: 成功率 ${successRate.toFixed(1)}%`, "info");
                    break;
                    
                case 'config_updated':
                case 'down_control_updated':
                    console.log('⚙️ 处理配置更新事件');
                    realDataStatus.status = true;
                    formatConfigUpdateEvent(eventPayload);
                    // 添加日志记录
                    addLog(`配置更新: ${eventPayload.parameter} 已更新`, "info");
                    break;
                    
                case 'image_detection':
                case 'image_show':
                    console.log('🖼️ 处理图像事件');
                    formatImageEvent(eventType, eventPayload);
                    // 添加日志记录
                    const typeName = eventType === 'image_detection' ? '图像检测' : '实时图像';
                    addLog(`${typeName}: 数据接收完成`, "info");
                    break;
                    
                case 'image_show':
                    console.log('🖼️ 处理实时图像显示事件');
                    handleImageData('image_show', eventPayload);
                    // 同时更新对比视图
                    updateComparisonImages();
                    break;

                case 'image_detection':
                    console.log('🖼️ 处理图像检测事件');
                    handleImageData('image_detection', eventPayload);
                    // 同时更新对比视图
                    updateComparisonImages();
                    break;

                case 'unknown':
                    console.log('❓ 处理未知事件类型');
                    // 尝试从数据中推断类型
                    const inferredType = inferEventType(eventPayload);
                    if (inferredType !== 'unknown') {
                        console.log(`🔄 推断事件类型为: ${inferredType}`);
                        handleEventData({...eventData, type: inferredType});
                    } else {
                        formatGenericEvent(eventType, eventPayload);
                        // 对于未知事件，也记录日志
                        addLog(`未知事件: ${JSON.stringify(eventPayload)}`, "warning");
                    }
                    break;
                    
                default:
                    console.log(`🔍 处理默认事件类型: ${eventType}`);
                    formatGenericEvent(eventType, eventPayload);
                    // 对于默认事件，根据类型决定是否记录日志
                    if (eventType.includes('error') || eventType.includes('emergency')) {
                        addLog(`错误事件: ${eventPayload.message || eventType}`, "error");
                    } else if (eventType.includes('move') || eventType.includes('detection')) {
                        addLog(`系统事件: ${eventPayload.message || eventType}`, "info");
                    }
                    // 其他类型事件不记录到系统日志
            }
        }

        // 新增：更新运行状态的函数
        function updateRunningStatus(eventType, eventPayload) {
            let runningStatus = '待机';
            let statusClass = 'status-info';
            
            switch(eventType) {
                case 'move_point':
                    runningStatus = '移动中';
                    statusClass = 'status-warning';
                    break;
                    
                case 'move_complete':
                    // 检查是否是回原点操作
                    if (eventPayload.message && 
                        (eventPayload.message.includes('回原点') || 
                        eventPayload.message.includes('goHome') ||
                        eventPayload.message.includes('原点'))) {
                        runningStatus = '回原点完成';
                        statusClass = 'status-success';
                    } else if (eventPayload.success) {
                        runningStatus = '移动完成';
                        statusClass = 'status-success';
                    } else {
                        runningStatus = '移动失败';
                        statusClass = 'status-error';
                    }
                    break;
                    
                case 'move_status':
                    runningStatus = '移动中';
                    statusClass = 'status-warning';
                    break;
                    
                case 'move_info':
                    if (eventPayload.overall_success) {
                        runningStatus = '任务执行中';
                        statusClass = 'status-warning';
                    } else {
                        runningStatus = '任务失败';
                        statusClass = 'status-error';
                    }
                    break;
                    
                case 'arm_stop':
                    if (!eventPayload.success) {
                        runningStatus = '紧急停止';
                        statusClass = 'status-error';
                    } else {
                        runningStatus = '恢复正常';
                        statusClass = 'status-success';
                    }
                    break;
                    
                case 'detection_result':
                    runningStatus = '检测中';
                    statusClass = 'status-info';
                    break;
                    
                case 'fire_status':
                    runningStatus = '发射中';
                    statusClass = 'status-warning';
                    break;
                    
                default:
                    // 保持当前状态不变
                    return;
            }
            
            // 更新状态数据表格中的运行状态
            updateStatusRunningStatus(runningStatus, statusClass);
            
            // 同时更新模拟数据，以便后续刷新时保持一致性
            updateMockRunningStatus(runningStatus, statusClass);
            
            console.log(`🔄 运行状态更新: ${runningStatus}`);
        }

        // 新增：更新状态数据表格中的运行状态
        function updateStatusRunningStatus(status, statusClass) {
            const tbody = document.querySelector('#status-data-table tbody');
            if (!tbody) return;
            
            const rows = tbody.querySelectorAll('tr');
            for (let row of rows) {
                const cells = row.querySelectorAll('td');
                if (cells.length >= 2 && cells[0].textContent === '运行状态') {
                    // 更新值
                    cells[1].textContent = status;
                    
                    // 更新状态徽章
                    if (cells.length >= 3) {
                        const statusBadge = cells[2].querySelector('.status-badge');
                        if (statusBadge) {
                            statusBadge.textContent = getStatusText(status);
                            statusBadge.className = `status-badge ${statusClass}`;
                        }
                    }
                    break;
                }
            }
        }

        // 新增：更新模拟数据中的运行状态
        function updateMockRunningStatus(status, statusClass) {
            for (let item of mockStatusData) {
                if (item.parameter === '运行状态') {
                    item.value = status;
                    item.status = getStatusText(status);
                    item.statusClass = statusClass;
                    break;
                }
            }
        }

        // 辅助函数：根据运行状态获取显示文本
        function getStatusText(runningStatus) {
            const statusMap = {
                '待机': '正常',
                '移动中': '进行中', 
                '回原点完成': '完成',
                '移动完成': '完成',
                '移动失败': '异常',
                '任务执行中': '进行中',
                '任务失败': '异常',
                '紧急停止': '异常',
                '恢复正常': '正常',
                '检测中': '进行中',
                '发射中': '进行中'
            };
            
            return statusMap[runningStatus] || '正常';
        }

        function inferEventType(data) {
            if (!data || typeof data !== 'object') return 'unknown';
            
            // 根据数据特征推断类型
            if (data.world_coord || data.point_id) return 'move_point';
            if (data.total_positions || data.valid_detect_points) return 'detection_result';
            if (data.end_effector_position) return 'end_effector_position';
            if (data.success_count !== undefined || data.total_count !== undefined) return 'operation_statistics';
            if (data.currents && Array.isArray(data.currents)) return 'joint_currents';
            if (data.event_type) return data.event_type;
            if (data.original_message) return 'arm_stop';
            
            return 'unknown';
        }

        // 格式化机械臂停止事件
        function formatArmStopEvent(data) {
            const eventType = data.event_type || '机械臂状态';
            const message = data.original_message || '无消息';
            const success = data.success;
            
            const event = {
                type: 'arm_status',
                message: `${eventType}: ${message}`,
                data: `状态: ${success ? '正常' : '异常'}, 错误码: ${data.error_code || '无'}`,
                class: success ? 'success' : 'error'
            };
            
            addEvent(event);
        }

        // 格式化检测结果事件
        function formatDetectionEvent(data) {
            const total = data.total_positions || 0;
            const validDetect = data.valid_detect_points || 0;
            const validUseful = data.valid_useful_points || 0;
            
            const event = {
                type: 'detection',
                message: `视觉检测完成: ${validUseful}个有用点`,
                data: `总位置: ${total}, 有效检测点: ${validDetect}, 有用点: ${validUseful}`,
                class: validUseful > 0 ? 'success' : 'warning'
            };
            
            // 如果有有用点，显示详细信息
            if (data.useful_points && data.useful_points.length > 0) {
                const pointsInfo = data.useful_points.map(point => 
                    `点${point.index}: 角度${point.angle}°, 坐标(${point.world_x}, ${point.world_y}, ${point.world_z})`
                ).join('; ');
                event.data += ` | 详情: ${pointsInfo}`;
            }
            
            // 更新总点数（检测到的总位置数）
            updateTotalPoints(total, '检测完成');
            
            addEvent(event);
        }

        function resetOperationTimer() {
            stopOperationTimer();
            operationStartTime = null;
            hasReceivedFirstEvent = false;
            
            // 重置显示
            updateStatusParameter('运行时间', '0秒', '待机', 'status-info');
            updateMockParameter('运行时间', '0秒', '待机', 'status-info');
            
            console.log('⏱️ 运行时间已重置');
            addLog("运行时间已重置", "info");
        }

        // 格式化移动完成事件
        function formatMoveCompleteEvent(data) {
            const success = data.success;
            const message = data.message || '移动操作完成';
            
            const event = {
                type: 'move_complete',
                message: message,
                data: `状态: ${data.status}, 代码: ${data.code || '无'}`,
                class: success ? 'success' : 'error'
            };
            
            // 如果是成功的移动完成，更新当前点坐标状态为完成
            if (success) {
                // 获取当前的坐标值（保持坐标不变，只更新状态）
                const tbody = document.querySelector('#status-data-table tbody');
                if (tbody) {
                    const rows = tbody.querySelectorAll('tr');
                    for (let row of rows) {
                        const cells = row.querySelectorAll('td');
                        if (cells.length >= 2 && cells[0].textContent === '当前点坐标') {
                            const currentValue = cells[1].textContent;
                            // 保持坐标值不变，只更新状态为完成
                            updateCurrentPointCoordinate({
                                world_coord: { x: 0, y: 0 }, // 坐标值不重要，会被忽略
                                is_moving: false,
                                is_completed: true,
                                preserveValue: currentValue // 保持现有值
                            });
                            break;
                        }
                    }
                }
                
                // 如果是回原点操作，重置总点数和成功点数（但不再重置运行时间）
                if (message.includes('回原点') || message.includes('goHome') || message.includes('原点')) {
                    updateTotalPoints(0, '完成');
                    updateSuccessPoints(0, 0, '完成');
                }
            }
            
            addEvent(event);
        }

        // 格式化发射状态事件
        function formatFireStatusEvent(data) {
            const event = {
                type: 'fire_status',
                message: `发射状态: ${data.status}`,
                data: `时间: ${new Date().toLocaleTimeString()}`,
                class: data.status.includes('成功') ? 'success' : 'info'
            };
            
            addEvent(event);
        }

        // 格式化移动点事件
        function formatMovePointEvent(data) {
            const pointId = data.point_id || '未知';
            const coords = data.world_coord || {};
            
            const event = {
                type: 'move_point',
                message: `移动到目标点 ID: ${pointId}`,
                data: `坐标: X=${coords.x?.toFixed(3) || 0}, Y=${coords.y?.toFixed(3) || 0}, Z=${coords.z?.toFixed(3) || 0}, 下潜: ${data.is_down ? '是' : '否'}`,
                class: 'info'
            };
            
            // 更新当前点ID
            updateCurrentPointId(pointId);
            
            // 更新当前点坐标，并标记为移动中
            updateCurrentPointCoordinate({
                world_coord: coords,
                is_moving: true,
                is_completed: false
            });
            
            // 设置总点数和成功点数为移动中状态（如果有数据）
            if (data.total_count !== undefined) {
                updateTotalPoints(data.total_count, '移动中');
                updateSuccessPoints(data.success_count || 0, data.total_count, '移动中');
            }
            
            addEvent(event);
        }

        function updateCurrentPointId(pointId) {
            // 更新当前状态数据中的点ID
            const statusTable = document.querySelector('#status-data-table tbody');
            if (statusTable) {
                const rows = statusTable.querySelectorAll('tr');
                for (let row of rows) {
                    const cells = row.querySelectorAll('td');
                    if (cells.length >= 2 && cells[0].textContent === '当前点ID') {
                        cells[1].textContent = pointId;
                        // 更新状态为"进行中"
                        if (cells.length >= 3) {
                            const statusBadge = cells[2].querySelector('.status-badge');
                            if (statusBadge) {
                                statusBadge.textContent = '进行中';
                                statusBadge.className = 'status-badge status-warning';
                            }
                        }
                        break;
                    }
                }
            }
                    // 同时更新模拟数据，以便后续刷新时保持一致性
            for (let item of mockStatusData) {
                if (item.parameter === '当前点ID') {
                    item.value = pointId;
                    item.status = '进行中';
                    item.statusClass = 'status-warning';
                    break;
                }
            }
            
            console.log(`✅ 当前点ID已更新为: ${pointId}`);
        }

        // 格式化移动状态事件
        function formatMoveStatusEvent(data) {
            const pointId = data.current_point_id || '未知';
            const successCount = data.success_count || 0;
            const totalCount = data.total_count || 0;
            const rate = data.completion_rate || 0;
            
            const event = {
                type: 'move_status',
                message: `移动状态更新 - 点${pointId}`,
                data: `进度: ${successCount}/${totalCount} (${rate.toFixed(1)}%)`,
                class: rate === 100 ? 'success' : 'info'
            };
            
            // 更新当前点坐标状态为移动中（如果进度不是100%）
            if (rate < 100) {
                // 保持现有的坐标值，只更新状态
                const tbody = document.querySelector('#status-data-table tbody');
                if (tbody) {
                    const rows = tbody.querySelectorAll('tr');
                    for (let row of rows) {
                        const cells = row.querySelectorAll('td');
                        if (cells.length >= 2 && cells[0].textContent === '当前点坐标') {
                            const currentValue = cells[1].textContent;
                            updateCurrentPointCoordinate({
                                preserveValue: currentValue,
                                is_moving: true,
                                is_completed: false
                            });
                            break;
                        }
                    }
                }
                
                // 更新总点数和成功点数为移动中状态
                updateTotalPoints(totalCount, '移动中');
                updateSuccessPoints(successCount, totalCount, '移动中');
            } else {
                // 如果进度是100%，更新为完成状态
                updateTotalPoints(totalCount, '完成');
                updateSuccessPoints(successCount, totalCount, '完成');
            }
            
            addEvent(event);
        }

        // 格式化移动信息事件（多阶段任务）
        function formatMoveInfoEvent(data) {
            const overallSuccess = data.overall_success;
            const overallMessage = data.overall_message || '任务执行';
            const stages = data.stages || [];
            
            // 检查是否是回原点操作
            const isGoHome = overallMessage.includes('回原点') || overallMessage.includes('goHome');
            
            // 计算总耗时
            const totalTime = stages.reduce((sum, stage) => sum + (stage.cost_time_ms || 0), 0);
            
            const event = {
                type: 'move_info',
                message: `${overallMessage} - ${overallSuccess ? '成功' : '失败'}`,
                data: `总耗时: ${totalTime}ms | ${stages.map(stage => 
                    `${stage.stage_name}(${stage.cost_time_ms}ms)${stage.success ? '✓' : '✗'}`
                ).join(' | ')}`,
                class: overallSuccess ? 'success' : 'error',
                overall_success: overallSuccess,
                isGoHome: isGoHome
            };
            
            addEvent(event);
        }

        // 修改 formatEndEffectorEvent 函数，移除其中的 addEvent 调用
        function formatEndEffectorEvent(data) {
            console.log('🎯 格式化末端事件数据:', data);
            
            let poseData = {};
            
            // 使用与 updateRealEndPose 相同的多种数据格式支持
            if (data.data && data.data.end_effector_position) {
                // 格式1: 嵌套在data.end_effector_position中
                poseData = data.data.end_effector_position;
            } else if (data.end_effector_position) {
                // 格式2: 直接包含end_effector_position
                poseData = data.end_effector_position;
            } else if (data.data) {
                // 格式3: 数据在data字段中
                poseData = data.data;
            } else {
                // 格式4: 数据本身就是姿态数据
                poseData = data;
            }
            
            // 构建完整的姿态对象，使用与实时数据相同的逻辑
            const endPose = {
                x: parseFloat(poseData.x) || parseFloat(poseData.position_x) || currentPose.x,
                y: parseFloat(poseData.y) || parseFloat(poseData.position_y) || currentPose.y,
                z: parseFloat(poseData.z) || parseFloat(poseData.position_z) || currentPose.z,
                rx: parseFloat(poseData.rx) || parseFloat(poseData.rotation_x) || currentPose.rx,
                ry: parseFloat(poseData.ry) || parseFloat(poseData.rotation_y) || currentPose.ry,
                rz: parseFloat(poseData.rz) || parseFloat(poseData.rotation_z) || currentPose.rz
            };
            
            console.log('📊 事件中的姿态数据:', endPose);
            
            // 注意：这里移除了 addEvent 调用，避免在事件记录中显示末端更新
            // 只更新数据，不记录事件
        }

        // 格式化运行统计事件
        function formatOperationStatsEvent(data) {
            const successRate = data.success_rate || 0;
            
            const event = {
                type: 'operation_statistics',
                message: `运行统计更新`,
                data: `成功率: ${successRate.toFixed(1)}%, 成功: ${data.success_count || 0}, 失败: ${data.failed_count || 0}, 总点数: ${data.total_points || 0}, 平均耗时: ${data.average_duration?.toFixed(2) || 0}s`,
                class: successRate > 80 ? 'success' : successRate > 60 ? 'warning' : 'error'
            };
            
            addEvent(event);
        }

        // 格式化关节电流事件
        // 修改 formatJointCurrentsEvent 函数，移除其中的 addEvent 调用（如果不需要在事件中显示）
        function formatJointCurrentsEvent(data) {
            const currents = data.currents || [];
            const jointCount = data.joint_count || currents.length;
            
            // 注意：这里移除了 addEvent 调用，避免在事件记录中显示关节电流更新
            // 只更新数据，不记录事件
            
            // 检查是否有异常电流值
            const highCurrents = currents.filter(c => c > 1.5);
            if (highCurrents.length > 0) {
                // 只有异常时才记录日志
                addLog(`关节电流异常: ${highCurrents.length}个关节电流过高`, "warning");
            }
        }

        // 格式化配置更新事件
        function formatConfigUpdateEvent(data) {
            const event = {
                type: 'config_updated',
                message: `配置文件已更新`,
                data: `参数: ${data.parameter}, 新值: ${data.new_value}, 文件: ${data.config_file}`,
                class: 'success'
            };
            
            addEvent(event);
        }

        // 格式化下探控制事件
        function formatDownControlEvent(data) {
            const event = {
                type: 'down_control',
                message: `下探控制命令: ${data.command}`,
                data: `时间: ${new Date(data.timestamp * 1000).toLocaleTimeString()}`,
                class: 'info'
            };
            
            addEvent(event);
        }

        // 格式化图像事件
        function formatImageEvent(eventType, data) {
            const typeName = eventType === 'image_detection' ? '图像检测' : '实时图像';
            
            const event = {
                type: eventType,
                message: `${typeName}数据接收`,
                data: `数据长度: ${data.data_length || 0} bytes`,
                class: 'info'
            };
            
            addEvent(event);
        }

        // 格式化通用事件
        function formatGenericEvent(eventType, data) {
            console.log('🔍 处理通用事件:', eventType, data);
            
            let message = '事件更新';
            let displayData = data;
            
            // 尝试从数据中提取有用信息
            if (typeof data === 'object' && data !== null) {
                if (data.message) {
                    message = data.message;
                } else if (data.content) {
                    message = data.content;
                } else if (data.original_message) {
                    message = data.original_message;
                }
                
                // 构建数据显示
                const dataParts = [];
                for (const [key, value] of Object.entries(data)) {
                    if (key !== 'message' && key !== 'content' && key !== 'original_message') {
                        if (typeof value === 'object') {
                            dataParts.push(`${key}: ${JSON.stringify(value)}`);
                        } else {
                            dataParts.push(`${key}: ${value}`);
                        }
                    }
                }
                displayData = dataParts.join(' | ');
            } else if (typeof data === 'string') {
                message = data;
                displayData = '';
            }
            
            const event = {
                type: eventType,
                message: message,
                data: displayData,
                class: 'info'
            };
            
            addEvent(event);
        }

        // 修改现有的 addEvent 函数，确保它能正确处理新的事件格式
        function addEvent(event) {
            try {
                const allContainer = document.getElementById('events-container-all');
                if (!allContainer) {
                    console.warn('事件容器未找到');
                    return;
                }

                // 创建事件元素
                const eventElement = document.createElement('div');
                
                // 设置事件类名
                let eventClass = event.class || '';
                let eventType = event.type || '未知事件';
                
                eventElement.className = `event-item ${eventClass}`;

                // 格式化时间
                const now = new Date();
                const time = now.toLocaleTimeString();

                // 安全地处理消息和数据
                const message = event.message || '无消息内容';
                let dataDisplay = '无数据';
                
                if (event.data) {
                    if (typeof event.data === 'string') {
                        dataDisplay = event.data;
                    } else if (typeof event.data === 'object') {
                        try {
                            dataDisplay = JSON.stringify(event.data, null, 2);
                        } catch (e) {
                            dataDisplay = '数据无法序列化';
                        }
                    } else {
                        dataDisplay = String(event.data);
                    }
                }

                eventElement.innerHTML = `
                    <div class="event-header">
                        <span class="event-type">${getEventTypeName(eventType)}</span>
                        <span class="event-time">${time}</span>
                    </div>
                    <div class="event-message">${escapeHtml(message)}</div>
                    <div class="event-data">${escapeHtml(dataDisplay)}</div>
                `;

                // 添加到顶部
                allContainer.insertBefore(eventElement, allContainer.firstChild);

                // 根据事件类型添加到相应的事件列表
                addEventToSpecificContainer(eventType, eventClass, eventElement);

                // 限制事件数量
                limitEventsCount(allContainer);

            } catch (error) {
                console.error('添加事件时出错:', error);
            }
        }

        function escapeHtml(unsafe) {
            if (!unsafe) return '';
            return unsafe
                .toString()
                .replace(/&/g, "&amp;")
                .replace(/</g, "&lt;")
                .replace(/>/g, "&gt;")
                .replace(/"/g, "&quot;")
                .replace(/'/g, "&#039;");
        }

        function addEventToSpecificContainer(eventType, eventClass, eventElement) {
            const containerMap = {
                'move': 'events-container-move',
                'detection': 'events-container-detection',
                'error': 'events-container-error'
            };

            let targetContainer = null;

            // 根据事件类型和类决定添加到哪个容器
            if (eventType.includes('move') || eventType === 'move_point' || eventType === 'move_status' || 
                eventType === 'move_info' || eventType === 'move_complete') {
                targetContainer = containerMap.move;
            } else if (eventType.includes('detection') || eventType === 'image_detection') {
                targetContainer = containerMap.detection;
            } else if (eventClass === 'error' || eventType.includes('error') || eventType.includes('emergency')) {
                targetContainer = containerMap.error;
            }

            if (targetContainer) {
                const specificContainer = document.getElementById(targetContainer);
                if (specificContainer) {
                    const clonedElement = eventElement.cloneNode(true);
                    specificContainer.insertBefore(clonedElement, specificContainer.firstChild);
                    limitEventsCount(specificContainer);
                }
            }
        }

                // 在 initWebSocket 函数中增加更详细的事件处理
        socket.on('ros_event_data', function(data) {
            console.log('📢 收到ROS事件数据:', data);
            
            try {
                // 如果数据是字符串，尝试解析
                if (typeof data === 'string') {
                    data = JSON.parse(data);
                }
                
                // 直接处理事件数据
                handleEventData(data);
            } catch (error) {
                console.error('❌ 处理ROS事件数据时出错:', error);
                console.error('原始数据:', data);
            }
        });

        // 确保其他数据通道也正常工作
        socket.on('ros_realtime_data', function(data) {
            console.log('📊 收到实时数据:', data);
            handleRealTimeData(data);
        });

        socket.on('ros_status_data', function(data) {
            console.log('📈 收到状态数据:', data);
            handleStatusData(data);
        });

        // 更新事件类型名称映射
        function getEventTypeName(type) {
            const typeMap = {
                'arm_stop': '机械臂状态',
                'detection_result': '视觉检测',
                'move_complete': '移动完成',
                'fire_status': '发射状态',
                'move_point': '移动点',
                'move_status': '移动状态',
                'move_info': '移动信息',
                'end_effector_position': '末端位置',
                'operation_statistics': '运行统计',
                'joint_currents': '关节电流',
                'config_updated': '配置更新',
                'down_control': '下探控制',
                'image_detection': '图像检测',
                'image_show': '实时图像',
                'arm_status': '机械臂状态',
                'detection': '检测结果'
            };

            return typeMap[type] || type;
        }

        // 修改 updateRealEndPose 函数，移除其中的 addLog 调用
        function updateRealEndPose(realData) {
            console.log('🎯 更新末端姿态:', realData);
            
            let poseData = {};
            
            // 多种数据格式支持
            if (realData.data && realData.data.end_effector_position) {
                // 格式1: 嵌套在data.end_effector_position中
                poseData = realData.data.end_effector_position;
            } else if (realData.end_effector_position) {
                // 格式2: 直接包含end_effector_position
                poseData = realData.end_effector_position;
            } else if (realData.data) {
                // 格式3: 数据在data字段中
                poseData = realData.data;
            } else {
                // 格式4: 数据本身就是姿态数据
                poseData = realData;
            }
            
            // 构建完整的姿态对象，提供默认值
            const endPose = {
                timestamp: realData.timestamp || new Date().toLocaleTimeString(),
                x: parseFloat(poseData.x) || parseFloat(poseData.position_x) || Math.random() * 0.1 + 1.2,
                y: parseFloat(poseData.y) || parseFloat(poseData.position_y) || Math.random() * 0.1 + 2.3,
                z: parseFloat(poseData.z) || parseFloat(poseData.position_z) || Math.random() * 0.05 + 0.1,
                rx: parseFloat(poseData.rx) || parseFloat(poseData.rotation_x) || (Math.random() - 0.5) * 10,
                ry: parseFloat(poseData.ry) || parseFloat(poseData.rotation_y) || (Math.random() - 0.5) * 10,
                rz: parseFloat(poseData.rz) || parseFloat(poseData.rotation_z) || (Math.random() - 0.5) * 10
            };
            
            console.log('📊 解析后的姿态数据:', endPose);
            
            // 更新当前姿态显示
            updateCurrentPose(endPose);
            
            // 添加到历史数据表格（如果表格存在）
            updatePositionData([endPose]);
            
            // 注意：这里移除了 addLog 调用，避免在系统日志中记录末端更新
            // 只更新数据，不记录日志
        }

        // 更新实时状态数据
        function updateRealTimeStatus(realData) {
            // 将后端数据结构转换为前端需要的格式
            const formattedData = formatStatusData(realData);
            updateStatusData(formattedData);
        }

        // 格式化状态数据
        function formatStatusData(realData) {
            // 根据您的后端数据结构进行调整
            return [
                { parameter: '运行状态', value: realData.status || '未知', status: '正常', statusClass: 'status-success' },
                { parameter: '电池电量', value: realData.battery + '%' || 'N/A', status: '良好', statusClass: 'status-success' },
                { parameter: '系统温度', value: realData.temperature + '°C' || 'N/A', status: '正常', statusClass: 'status-info' },
                // ... 其他字段
            ];
        }

        // 添加真实事件
        function addRealEvent(eventData) {
            const event = {
                type: eventData.type || 'unknown',
                time: eventData.timestamp || new Date().toLocaleTimeString(),
                message: eventData.message || eventData.content || '事件更新',
                data: JSON.stringify(eventData.data || eventData),
                class: getEventClassByType(eventData.type || eventData.level)
            };
            
            // 使用现有的addEvent函数
            addEvent(event);
        }

        // 根据事件类型获取CSS类
        function getEventClassByType(type) {
            const typeMap = {
                'error': 'error',
                'warning': 'warning',
                'info': '',
                'success': 'success',
                'emergency': 'error'
            };
            return typeMap[type] || '';
        }

        // 更新性能数据表格
        function updatePerformanceData(performanceData) {
            const tbody = document.querySelector('#performance-data-table tbody');
            tbody.innerHTML = '';

            performanceData.forEach(item => {
                const row = document.createElement('tr');
                row.innerHTML = `
                    <td>${item.component}</td>
                    <td>${item.cpu}</td>
                    <td>${item.memory}</td>
                    <td>${item.temperature}</td>
                    <td><span class="status-badge ${item.statusClass || 'status-info'}">${item.status}</span></td>
                `;
                tbody.appendChild(row);
            });
        }

        // 更新网络数据表格
        function updateNetworkData(networkData) {
            const tbody = document.querySelector('#network-data-table tbody');
            tbody.innerHTML = '';

            networkData.forEach(item => {
                const row = document.createElement('tr');
                row.innerHTML = `
                    <td>${item.connection}</td>
                    <td>${item.ip}</td>
                    <td>${item.upload}</td>
                    <td>${item.download}</td>
                    <td>${item.latency}</td>
                `;
                tbody.appendChild(row);
            });
        }

        // 更新所有事件列表
        function updateEvents() {
            // 更新全部事件
            const allContainer = document.getElementById('events-container-all');
            allContainer.innerHTML = '';
            mockEvents.all.forEach(event => {
                const eventElement = createEventElement(event);
                allContainer.appendChild(eventElement);
            });

            // 更新移动事件
            const moveContainer = document.getElementById('events-container-move');
            moveContainer.innerHTML = '';
            mockEvents.move.forEach(event => {
                const eventElement = createEventElement(event);
                moveContainer.appendChild(eventElement);
            });

            // 更新检测事件
            const detectionContainer = document.getElementById('events-container-detection');
            detectionContainer.innerHTML = '';
            mockEvents.detection.forEach(event => {
                const eventElement = createEventElement(event);
                detectionContainer.appendChild(eventElement);
            });

            // 更新错误事件
            const errorContainer = document.getElementById('events-container-error');
            errorContainer.innerHTML = '';
            mockEvents.error.forEach(event => {
                const eventElement = createEventElement(event);
                errorContainer.appendChild(eventElement);
            });
        }

        // 创建事件元素
        function createEventElement(event) {
            const eventElement = document.createElement('div');
            eventElement.className = `event-item ${event.class}`;

            eventElement.innerHTML = `
                <div class="event-header">
                    <span class="event-type">${getEventTypeName(event.type)}</span>
                    <span class="event-time">${event.time}</span>
                </div>
                <div class="event-message">${event.message}</div>
                <div class="event-data">${event.data}</div>
            `;

            return eventElement;
        }

        // 添加单个事件
        function addEvent(event) {
            const allContainer = document.getElementById('events-container-all');

            // 创建事件元素
            const eventElement = document.createElement('div');

            // 根据事件类型确定样式类
            let eventClass = '';
            if (event.type.includes('error') || event.type.includes('emergency')) {
                eventClass = 'error';
            } else if (event.type.includes('success') || event.type.includes('complete')) {
                eventClass = 'success';
            } else if (event.type.includes('warning')) {
                eventClass = 'warning';
            }

            eventElement.className = `event-item ${eventClass}`;

            // 格式化时间
            const now = new Date();
            const time = now.toTimeString().split(' ')[0];

            eventElement.innerHTML = `
                <div class="event-header">
                    <span class="event-type">${getEventTypeName(event.type)}</span>
                    <span class="event-time">${time}</span>
                </div>
                <div class="event-message">${event.message || '无消息'}</div>
                <div class="event-data">${JSON.stringify(event.data) || '无数据'}</div>
            `;

            // 添加到顶部
            allContainer.insertBefore(eventElement, allContainer.firstChild);

            // 根据事件类型添加到相应的事件列表
            if (event.type.includes('move')) {
                const moveContainer = document.getElementById('events-container-move');
                const moveEventElement = eventElement.cloneNode(true);
                moveContainer.insertBefore(moveEventElement, moveContainer.firstChild);
            } else if (event.type.includes('detection')) {
                const detectionContainer = document.getElementById('events-container-detection');
                const detectionEventElement = eventElement.cloneNode(true);
                detectionContainer.insertBefore(detectionEventElement, detectionContainer.firstChild);
            } else if (event.type.includes('error') || event.type.includes('emergency')) {
                const errorContainer = document.getElementById('events-container-error');
                const errorEventElement = eventElement.cloneNode(true);
                errorContainer.insertBefore(errorEventElement, errorContainer.firstChild);
            }

            // 限制事件数量
            limitEventsCount(allContainer);
            limitEventsCount(document.getElementById('events-container-move'));
            limitEventsCount(document.getElementById('events-container-detection'));
            limitEventsCount(document.getElementById('events-container-error'));
        }

        // 限制事件数量
        function limitEventsCount(container) {
            if (container && container.children.length > 50) {
                container.removeChild(container.lastChild);
            }
        }

        // 获取事件类型名称
        function getEventTypeName(type) {
            const typeMap = {
                'move_point': '移动点',
                'move_status': '移动状态',
                'move_info': '移动信息',
                'detection': '检测结果',
                'emergency': '紧急事件',
                'error': '错误',
                'status': '状态更新',
                'move_complete': '移动完成'
            };

            return typeMap[type] || type;
        }

        // 添加日志条目
        function addLog(message, type = 'info') {
            const logContainer = document.getElementById('log-container');
            const logEntry = document.createElement('div');
            logEntry.className = `log-entry ${type}`;

            // 添加时间戳
            const now = new Date();
            const timestamp = now.toTimeString().split(' ')[0];

            // 添加图标
            let icon = 'fa-info-circle';
            if (type === 'success') icon = 'fa-check-circle';
            else if (type === 'warning') icon = 'fa-exclamation-triangle';
            else if (type === 'error') icon = 'fa-exclamation-circle';

            logEntry.innerHTML = `
                <span class="log-time">[${timestamp}]</span>
                <i class="fas ${icon}"></i>
                <span>${message}</span>
            `;

            logContainer.appendChild(logEntry);
            // 自动滚动到底部
            logContainer.scrollTop = logContainer.scrollHeight;

            // 更新日志计数
            updateLogCount();

            // 如果日志太多，移除最旧的日志
            if (logContainer.children.length > 100) {
                logContainer.removeChild(logContainer.firstChild);
            }
        }

        // 更新日志计数
        function updateLogCount() {
            const logContainer = document.getElementById('log-container');
            const logCountElement = document.getElementById('log-count');
            logCountElement.textContent = logContainer.children.length;
        }

        // 创建模拟检测框
        function createDetectionBoxes() {
            const overlay1 = document.getElementById('detection-overlay-1');
            const overlay2 = document.getElementById('detection-overlay-2');
            const overlay3 = document.getElementById('comparison-detection-1');
            const overlay4 = document.getElementById('comparison-detection-2');

            overlay1.innerHTML = '';
            overlay2.innerHTML = '';
            overlay3.innerHTML = '';
            overlay4.innerHTML = '';

            // 创建几个随机位置的检测框
            for (let i = 0; i < 5; i++) {
                // 第一张图像的检测框
                const box1 = document.createElement('div');
                box1.className = 'detection-box';

                // 随机位置和大小
                const left1 = 10 + Math.random() * 70;
                const top1 = 10 + Math.random() * 70;
                const width1 = 10 + Math.random() * 15;
                const height1 = 10 + Math.random() * 15;

                box1.style.left = `${left1}%`;
                box1.style.top = `${top1}%`;
                box1.style.width = `${width1}%`;
                box1.style.height = `${height1}%`;

                // 添加标签
                const label1 = document.createElement('div');
                label1.className = 'detection-label';
                label1.textContent = `目标 ${i + 1}`;
                label1.style.left = `${left1}%`;
                label1.style.top = `${top1}%`;

                overlay1.appendChild(box1);
                overlay1.appendChild(label1);

                // 对比视图中的第一张图
                const box3 = box1.cloneNode(true);
                const label3 = label1.cloneNode(true);
                overlay3.appendChild(box3);
                overlay3.appendChild(label3);

                // 第二张图像的检测框（稍微不同的位置）
                const box2 = document.createElement('div');
                box2.className = 'detection-box';

                const left2 = Math.max(5, Math.min(85, left1 + (Math.random() * 10 - 5)));
                const top2 = Math.max(5, Math.min(85, top1 + (Math.random() * 10 - 5)));
                const width2 = Math.max(8, Math.min(20, width1 + (Math.random() * 4 - 2)));
                const height2 = Math.max(8, Math.min(20, height1 + (Math.random() * 4 - 2)));

                box2.style.left = `${left2}%`;
                box2.style.top = `${top2}%`;
                box2.style.width = `${width2}%`;
                box2.style.height = `${height2}%`;

                const label2 = document.createElement('div');
                label2.className = 'detection-label';
                label2.textContent = `目标 ${i + 1}`;
                label2.style.left = `${left2}%`;
                label2.style.top = `${top2}%`;

                overlay2.appendChild(box2);
                overlay2.appendChild(label2);

                // 对比视图中的第二张图
                const box4 = box2.cloneNode(true);
                const label4 = label2.cloneNode(true);
                overlay4.appendChild(box4);
                overlay4.appendChild(label4);
            }
        }

        // 图片缩放功能
        function zoomImage(containerId, delta) {
            const container = document.getElementById(containerId);
            imageZoomLevels[containerId] = Math.max(0.5, Math.min(2, imageZoomLevels[containerId] + delta));
            container.style.transform = `scale(${imageZoomLevels[containerId]})`;
            addLog(`图片缩放: ${Math.round(imageZoomLevels[containerId] * 100)}%`, "info");
        }

        // 图片对比缩放功能（同步缩放）
        function zoomComparison(delta) {
            const innerContainer = document.getElementById('comparison-inner');
            imageZoomLevels['comparison-container'] = Math.max(0.5, Math.min(2, imageZoomLevels['comparison-container'] + delta));
            innerContainer.style.transform = `scale(${imageZoomLevels['comparison-container']})`;
            addLog(`对比图片缩放: ${Math.round(imageZoomLevels['comparison-container'] * 100)}%`, "info");
        }

        // 重置图片缩放
        function resetZoom(containerId) {
            const container = document.getElementById(containerId);
            imageZoomLevels[containerId] = 1;
            container.style.transform = `scale(1)`;
            addLog("图片缩放已重置", "info");
        }

        // 重置对比图片缩放
        function resetComparisonZoom() {
            const innerContainer = document.getElementById('comparison-inner');
            imageZoomLevels['comparison-container'] = 1;
            innerContainer.style.transform = `scale(1)`;
            addLog("对比图片缩放已重置", "info");
        }

        // 修改 simulateDataUpdate 函数，只在没有真实数据时使用模拟数据
        function simulateDataUpdate() {
            // 检查是否有真实数据
            const now = new Date();
            const timeSinceLastRealData = realDataStatus.lastRealDataTime ? 
                (now - realDataStatus.lastRealDataTime) / 1000 : Infinity;
            
            // 如果最近10秒内收到过真实数据，不使用模拟数据
            if (timeSinceLastRealData < 10) {
                console.log('📡 最近收到真实数据，跳过模拟更新');
                return;
            }
            
            // 如果WebSocket连接正常，也不使用模拟数据
            if (socket && socket.connected) {
                console.log('📡 WebSocket连接正常，跳过模拟更新');
                return;
            }
            
            console.log('🎭 运行模拟数据更新（无真实数据）');
            
            // 如果正在使用模拟数据且有计时器在运行，停止计时器
            if (isUsingRealData && operationTimer) {
                stopOperationTimer();
                isUsingRealData = false;
                addLog("切换到模拟数据模式，运行时间暂停", "warning");
            }
            
            // 随机更新一些数据点状态
            mockStatusData.forEach(item => {
                if (item.parameter === '成功点数') {
                    const [success, total] = item.value.split('/');
                    const newSuccess = Math.min(parseInt(success) + Math.floor(Math.random() * 2), parseInt(total));
                    item.value = `${newSuccess}/${total}`;
                    item.status = newSuccess === parseInt(total) ? '完成' : '进行中';
                    item.statusClass = newSuccess === parseInt(total) ? 'status-success' : 'status-warning';
                }
                
                // 注意：运行时间不再随机更新，由计时器控制
                // 只在模拟模式下且计时器未启动时更新运行时间
                if (item.parameter === '运行时间' && !operationTimer) {
                    const timeParts = item.value.match(/(\d+)小时(\d+)分(\d+)秒/) || 
                                    item.value.match(/(\d+)分(\d+)秒/) || 
                                    item.value.match(/(\d+)秒/);
                    
                    if (timeParts) {
                        let seconds = 0;
                        if (timeParts[1] && timeParts[2] && timeParts[3]) {
                            // 小时:分钟:秒格式
                            seconds = parseInt(timeParts[1]) * 3600 + parseInt(timeParts[2]) * 60 + parseInt(timeParts[3]);
                        } else if (timeParts[1] && timeParts[2]) {
                            // 分钟:秒格式
                            seconds = parseInt(timeParts[1]) * 60 + parseInt(timeParts[2]);
                        } else if (timeParts[1]) {
                            // 秒格式
                            seconds = parseInt(timeParts[1]);
                        }
                        
                        // 增加1秒
                        seconds += 1;
                        
                        // 重新格式化为字符串
                        const hours = Math.floor(seconds / 3600);
                        const minutes = Math.floor((seconds % 3600) / 60);
                        const secs = seconds % 60;
                        
                        if (hours > 0) {
                            item.value = `${hours}小时${minutes}分${secs}秒`;
                        } else if (minutes > 0) {
                            item.value = `${minutes}分${secs}秒`;
                        } else {
                            item.value = `${secs}秒`;
                        }
                    }
                }
            });

            updateStatusData(mockStatusData);

            // 添加新的位置数据
            const timestamp = `${now.getHours().toString().padStart(2, '0')}:${now.getMinutes().toString().padStart(2, '0')}:${now.getSeconds().toString().padStart(2, '0')}.${now.getMilliseconds().toString().padStart(3, '0')}`;

            const newPositionData = {
                timestamp: timestamp,
                x: 1.2 + Math.random() * 0.1,
                y: 2.3 + Math.random() * 0.1,
                z: 0.1 + Math.random() * 0.05,
                rx: (Math.random() - 0.5) * 20,
                ry: (Math.random() - 0.5) * 20,
                rz: (Math.random() - 0.5) * 20
            };

            mockPositionData.unshift(newPositionData);
            while (mockPositionData.length > 10) mockPositionData.pop();

            updatePositionData(mockPositionData);
            updateCurrentPose(newPositionData);

            // 随机更新传感器数据
            mockSensorsData[0].value = (2 + Math.random() * 1).toFixed(2);
            mockSensorsData[2].value = (0.3 + Math.random() * 0.5).toFixed(2);
            updateSensorsData(mockSensorsData);

            // 随机更新性能数据
            mockPerformanceData[0].cpu = Math.floor(Math.random() * 30 + 20) + '%';
            mockPerformanceData[1].cpu = Math.floor(Math.random() * 30 + 50) + '%';
            updatePerformanceData(mockPerformanceData);

            // 随机添加新事件
            if (Math.random() > 0.7) {
                const eventTypes = ['move_point', 'detection', 'status'];
                const messages = [
                    '机械臂移动到新位置',
                    '检测到目标点',
                    '系统状态更新',
                    '数据点处理完成',
                    '视觉检测进行中'
                ];

                const newEvent = {
                    type: eventTypes[Math.floor(Math.random() * eventTypes.length)],
                    message: messages[Math.floor(Math.random() * messages.length)],
                    data: '随机生成的事件数据'
                };

                addEvent(newEvent);
            }

            // 随机添加新日志
            const logTypes = ['info', 'success'];
            const logMessages = [
                '数据点处理完成',
                '机械臂移动中',
                '视觉检测进行中',
                '系统运行正常',
                '数据传输中'
            ];

            if (Math.random() > 0.5) {
                const type = logTypes[Math.floor(Math.random() * logTypes.length)];
                const message = logMessages[Math.floor(Math.random() * messages.length)];
                addLog(message, type);
            }
        }

        // 修改 updateConnectionStatus 函数，显示真实数据状态
        function updateConnectionStatus() {
            const statusItems = document.querySelectorAll('.status-item');
            const now = new Date();
            const timeSinceLastRealData = realDataStatus.lastRealDataTime ? 
                (now - realDataStatus.lastRealDataTime) / 1000 : Infinity;
            
            statusItems.forEach(item => {
                const text = item.textContent;
                
                // 数据接收状态
                if (text.includes('数据接收中')) {
                    const dot = item.querySelector('.status-dot');
                    if (timeSinceLastRealData < 5) { // 5秒内有真实数据
                        dot.classList.add('active');
                        item.innerHTML = `<div class="status-dot active"></div><span>数据接收中 - 真实数据</span>`;
                    } else if (socket && socket.connected) {
                        dot.classList.add('active');
                        item.innerHTML = `<div class="status-dot active"></div><span>数据接收中 - 等待数据</span>`;
                    } else {
                        dot.classList.remove('active');
                        item.innerHTML = `<div class="status-dot"></div><span>数据接收中 - 模拟数据</span>`;
                    }
                }
                
                // 末端数据状态
                if (text.includes('视觉系统在线')) {
                    const dot = item.querySelector('.status-dot');
                    if (realDataStatus.endEffector && timeSinceLastRealData < 5) {
                        dot.classList.add('active');
                        item.innerHTML = `<div class="status-dot active"></div><span>末端数据: 真实数据</span>`;
                    } else if (endEffectorData.connectionStatus === 'connected') {
                        dot.classList.add('active');
                        const timeDiff = new Date() - endEffectorData.lastUpdate;
                        const secondsAgo = Math.floor(timeDiff / 1000);
                        item.innerHTML = `<div class="status-dot active"></div><span>末端数据: 模拟 (${secondsAgo}s前)</span>`;
                    } else {
                        dot.classList.remove('active');
                        item.innerHTML = `<div class="status-dot"></div><span>末端数据: 离线</span>`;
                    }
                }
                
                // 关节数据状态
                if (text.includes('机械臂就绪')) {
                    const dot = item.querySelector('.status-dot');
                    if (realDataStatus.joints && timeSinceLastRealData < 5) {
                        dot.classList.add('active');
                        item.innerHTML = `<div class="status-dot active"></div><span>关节数据: 真实数据</span>`;
                    } else {
                        dot.classList.add('active');
                        item.innerHTML = `<div class="status-dot active"></div><span>关节数据: 模拟数据</span>`;
                    }
                }
            });
        }

        // 添加数据源显示函数
        function updateDataSourceDisplay() {
            const now = new Date();
            const timeSinceLastRealData = realDataStatus.lastRealDataTime ? 
                (now - realDataStatus.lastRealDataTime) / 1000 : Infinity;
            
            // 在适当位置显示数据源信息
            const dataSourceElement = document.getElementById('data-source-display') || createDataSourceDisplay();
            
            if (timeSinceLastRealData < 5) {
                dataSourceElement.innerHTML = `
                    <div style="background: var(--accent-green); color: white; padding: 5px 10px; border-radius: 5px; font-size: 12px;">
                        <i class="fas fa-check-circle"></i> 使用真实数据
                    </div>
                `;
            } else if (socket && socket.connected) {
                dataSourceElement.innerHTML = `
                    <div style="background: var(--accent-orange); color: white; padding: 5px 10px; border-radius: 5px; font-size: 12px;">
                        <i class="fas fa-sync-alt"></i> 等待真实数据...
                    </div>
                `;
            } else {
                dataSourceElement.innerHTML = `
                    <div style="background: var(--accent-blue); color: white; padding: 5px 10px; border-radius: 5px; font-size: 12px;">
                        <i class="fas fa-desktop"></i> 使用模拟数据
                    </div>
                `;
            }
        }

        // 创建数据源显示元素
        function createDataSourceDisplay() {
            const header = document.querySelector('header');
            const dataSourceElement = document.createElement('div');
            dataSourceElement.id = 'data-source-display';
            dataSourceElement.style.marginLeft = '15px';
            header.appendChild(dataSourceElement);
            return dataSourceElement;
        }

        function handleWebSocketConnect() {
            useRealData = true;
            addLog("切换到真实数据模式", "success");
        }

        // 刷新实时数据
        function refreshRealTimeData() {
            addLog("手动刷新状态数据", "info");
            // 这里应该调用API获取最新数据
        }

        // 切换自动刷新
        function toggleAutoRefresh() {
            const button = document.querySelector('.data-action-btn:nth-child(2)');
            const isAuto = button.innerHTML.includes('暂停');

            if (isAuto) {
                button.innerHTML = '<i class="fas fa-play-circle"></i> 自动刷新';
                addLog("已暂停自动刷新", "warning");
            } else {
                button.innerHTML = '<i class="fas fa-pause-circle"></i> 暂停刷新';
                addLog("已启用自动刷新", "success");
            }
        }

        // 清除事件
        function clearEvents() {
            if (confirm("确定要清除所有事件吗？")) {
                document.getElementById('events-container-all').innerHTML = '';
                document.getElementById('events-container-move').innerHTML = '';
                document.getElementById('events-container-detection').innerHTML = '';
                document.getElementById('events-container-error').innerHTML = '';
                addLog("已清除所有事件", "info");
            }
        }

        // 清除特定类型事件
        function clearMoveEvents() {
            if (confirm("确定要清除所有移动事件吗？")) {
                document.getElementById('events-container-move').innerHTML = '';
                addLog("已清除所有移动事件", "info");
            }
        }

        function clearDetectionEvents() {
            if (confirm("确定要清除所有检测事件吗？")) {
                document.getElementById('events-container-detection').innerHTML = '';
                addLog("已清除所有检测事件", "info");
            }
        }

        function clearErrorEvents() {
            if (confirm("确定要清除所有错误事件吗？")) {
                document.getElementById('events-container-error').innerHTML = '';
                addLog("已清除所有错误事件", "info");
            }
        }

        // 导出事件
        function exportEvents() {
            addLog("导出所有事件数据", "info");
            // 这里应该实现导出功能
        }

        // 导出特定类型事件
        function exportMoveEvents() {
            addLog("导出移动事件数据", "info");
            // 这里应该实现导出功能
        }

        function exportDetectionEvents() {
            addLog("导出检测事件数据", "info");
            // 这里应该实现导出功能
        }

        function exportErrorEvents() {
            addLog("导出错误事件数据", "info");
            // 这里应该实现导出功能
        }

        // 清除日志
        function clearLogs() {
            if (confirm("确定要清除所有日志吗？")) {
                document.getElementById('log-container').innerHTML = '';
                updateLogCount();
                addLog("已清除所有日志", "info");
            }
        }

        // 导出日志
        function exportLogs() {
            addLog("导出日志数据", "info");
            // 这里应该实现导出功能
        }

        // 刷新其他数据
        function refreshPositionData() {
            addLog("手动刷新位置数据", "info");
        }

        function refreshJointsData() {
            addLog("手动刷新关节数据", "info");
        }

        function refreshSensorsData() {
            addLog("手动刷新传感器数据", "info");
        }

        function refreshPerformanceData() {
            addLog("手动刷新性能数据", "info");
        }

        function refreshNetworkData() {
            addLog("手动刷新网络数据", "info");
        }

        // 导出其他数据
        function exportPositionData() {
            addLog("导出位置数据", "info");
        }

        function exportJointsData() {
            addLog("导出关节数据", "info");
        }

        function exportSensorsData() {
            addLog("导出传感器数据", "info");
        }

        function exportPerformanceData() {
            addLog("导出性能数据", "info");
        }

        function exportNetworkData() {
            addLog("导出网络数据", "info");
        }

        // 机械臂控制函数
        function armProcess() {
            addLog("启动机械臂处理过程...", "info");
            callAPI('/api/arm/process');
        }

        function armClearError() {
            addLog("清除机械臂错误...", "info");
            callAPI('/api/arm/clearError');
        }

        function armGoHome() {
            addLog("机械臂回原点...", "info");
            callAPI('/api/arm/goHome');
        }

        function armEmergency(status) {
            const actions = { 1: "紧急停止", 2: "暂停", 3: "恢复" };
            addLog(`执行${actions[status]}操作...`, "warning");
            callAPI('/api/arm/emergency', 'POST', { status: status });
        }

        function controlRosNode(action) {
            const actions = { 1: "启动ROS节点", 2: "重启ROS节点", 3: "停止ROS节点" };
            addLog(`${actions[action]}...`, "info");
            callAPI('/api/ros/status', 'POST', { status: action });
        }

        function showAdvancedControls() {
            addLog("打开高级设置面板", "info");
            // 在实际应用中这里会打开一个模态窗口或展开更多控制选项
        }

        // API调用函数
        async function callAPI(endpoint, method = 'GET', data = null) {
            // 确保endpoint以/开头，并且路径正确
            const options = {
                method: method,
                headers: {
                    'Content-Type': 'application/json',
                },
            };
            const host = window.location.hostname || '10.0.0.7';
            const port = window.location.port || '7722';
            
            // 如果endpoint已经是完整路径，直接使用；否则添加前缀
            let fullEndpoint = endpoint;
            if (!endpoint.startsWith('/api/')) {
                // 根据endpoint类型添加正确的前缀
                if (endpoint.includes('arm')) {
                    fullEndpoint = '/api/arm' + endpoint;
                } else if (endpoint.includes('msg')) {
                    fullEndpoint = '/api/msg' + endpoint;
                } else if (endpoint.includes('ros')) {
                    fullEndpoint = '/api/ros' + endpoint;
                } else {
                    fullEndpoint = '/api' + endpoint;
                }
            }
            
            const url = `http://${host}:${port}${fullEndpoint}`;

            if (data) options.body = JSON.stringify(data);

            addLog(`调用API: ${method} ${url}`, 'info');
            try {
                const resp = await fetch(url, options);
                if (!resp.ok) {
                    throw new Error(`HTTP ${resp.status} ${resp.statusText}`);
                }
                const result = await resp.json();
                addLog(`API调用成功: ${result.message}`, 'success');
                return result;
            } catch (err) {
                addLog(`API调用失败: ${err.message}`, 'error');
                throw err;
            }
        }
    </script>
</body>

</html>